c# - 检测父任务取消的正确方法是什么?

标签 c# c#-4.0 task semaphore

我正在开发一个概念验证应用程序,该应用程序使用任务和信号量对数字列表进行分解,目前我有一个任务列表,List<Task> , 那需要 FactorNumberClass然后计算FactorNumberClass内具体数字的因数这目前工作正常。对于每个任务 T,我都有一个 ContinueWith任务更新因式分解总数的进度、因式分解的平均时间,并使用(成功分解的数字)/(要分解的总数)的值更新进度条。当分解这些 Tasks输入 SemaphoreSlim.Wait(cancelToken)将当前因数限制为 5 active Tasks .最后我有一个 ContinueWhenAll当所有任务完成时记录。假设没有取消,这一切都按我的预期进行。

当我尝试取消任务时出现问题,我无法检测任务是否已被取消,因此无法准确确定该数字是否已成功分解或是否被取消。如何检测父任务是否已取消或运行完成?

取消 token 定义:

public static CancellationTokenSource tokenSource = new CancellationTokenSource();
public static CancellationToken ct = tokenSource.Token;

因子类代码:

public class FactorNumberClass
{
    public FactorNumberClass()
    {
    }

    public FactorNumberClass(int num, int threadnum)
    {
        this.number = num;
        this.threadNumber = threadnum;
    }

    public List<int> factors = new List<int>();
    public int number;
    public int max;
    public int threadNumber;
}

因式分解方法:

public void Factor(FactorNumberClass F, CancellationToken token)
        {
            LogtoStatusText("Thread: " + F.threadNumber + " Trying to enter semaphore");

            try
            {
                ASemaphore.Wait(ct);

                F.max = (int)Math.Sqrt(F.number);  //round down

                for (int factor = 1; factor <= F.max; ++factor)
                { //test from 1 to the square root, or the int below it, inclusive.
                    if (F.number % factor == 0)
                    {
                        F.factors.Add(factor);
                        if (factor != F.number / factor)
                        {
                            F.factors.Add(F.number / factor);
                        }
                    }
                }

                F.factors.Sort();
                Thread.Sleep(F.number * 300);
                LogtoStatusText("Task: " + F.threadNumber + " Completed - Factors: " + string.Join(",", F.factors.ToArray()));
                LogtoStatusText("Thread: " + F.threadNumber + " Releases semaphore with previous count: " + ASemaphore.Release());
            }
            catch (OperationCanceledException ex)
            {
                LogtoStatusText("Thread: " + F.threadNumber + " Cancelled.");
            }
            finally
            {
            }
        }

开始处理的方法:

public void btnStart_Click(object sender, RoutedEventArgs e)
        {
            Task T;
            List<Task> TaskList = new List<Task>();
            LogtoStatusText("**** Begin creating tasks *****");
            s1.Start();

            AProject.FactorClassList.ForEach((f) =>
            {
                T = new Task(((x) => { OnUIThread(() => { RunningTasks++; }); Factor(f, ct); }), ct);

                T.ContinueWith((y) =>
                {
                    if (y.IsCompleted)
                    {
                        AProject.TotalProcessedAccounts++;
                        AProject.AverageProcessTime = (((Double)AProject.TotalProcessedAccounts / s1.ElapsedMilliseconds) * 1000);
                    }
                    OnUIThread(() => { RunningTasks--; });
                    OnUIThread(() => { UpdateCounts(AProject); });
                });

                TaskList.Add(T);
            });

            try
            {
                Task.Factory.ContinueWhenAll(TaskList.ToArray(), (z) => { LogtoStatusText("**** Completed all Tasks *****"); OnUIThread(() => { UpdateCounts(AProject); }); });
            }
            catch (AggregateException a)
            {
                // For demonstration purposes, show the OCE message.
                foreach (var v in a.InnerExceptions)
                    LogtoStatusText("msg: " + v.Message);
            }

            LogtoStatusText("**** All tasks have been initialized, begin processing *****");
            TaskList.ForEach(t => t.Start());
        }

最佳答案

释放finally block 中的信号量,以便它始终正确释放。无需检测取消。

此外,隐藏在日志消息中的副作用也不是好的风格:

LogtoStatusText("..." + ASemaphore.Release());

我只是通过文本搜索找到的。否则永远不会注意到这个错误。

关于c# - 检测父任务取消的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30101682/

相关文章:

if-statement - 在单个条件下对多个 ansible 任务进行分组

c# - 调度员不调度

c# - 可以将 FTP 与 Amazon S3/Google Drive/OneDrive 一起使用吗?

c# - Redis缓存InvalidOperationException : Reading is not allowed after reader was completed

sql-server - 在没有实体类的情况下动态构建 LINQ to SQL 查询

c# - 如何将数据库中的枚举保存为字符串

java - 无法在静态方法中将 JavaFx 任务委托(delegate)给新线程

c# - 通过反射调用 this[int index]

c# - WebResponse contentLength 属性是-1?

c# - 我如何测试 FileSystemWatcher 引发正确的事件?