如何继续完成任务?

时间:2016-06-01 08:57:51

标签: c# multithreading

public int CalcGroup(CancellationTokenSource cts)
{
    try
    {
        CancellationToken ct = cts.Token;
        if (cts.IsCancellationRequested == true && TaskWorkStatus.IsContinue == false) return 0;

        for (int i = 0; i < _paralellTaskCount; i++)
        {
            int counter = CheckCounter(message);
            if (counter >= 0)
            {
                var myTask = new Task<long>(() => CalcSingle(_personnelIds[counter].Item1), ct, TaskCreationOptions.LongRunning);
                if(myTask.IsCompleted)
                    myTask.ContinueWith(t => CalcSingle(_personnelIds[counter].Item1), ct);
                else
                    myTask.Start();

            }
        }
    }
    catch (Exception)
    {
        return 0;
    }
    return 1;
}

在上面的代码块中,我想运行CanceledCompleted的任务,但它不起作用。
我的错是什么?

1 个答案:

答案 0 :(得分:1)

0)通过构造函数创建一个新的任务是一个不好的做法,因为运行它将在以后产生额外的开销(你可以谷歌为什么和后来如何)。使用Task.Run或Task.Factory.StartNew,具体取决于您的.NET版本。(我最近了解到,对于.NET 4.5及更高版本,Task.Run是一种更好的做法。)

1)创建任务不会启动它,因此当前逻辑将始终跳过第一个条件,启动任务并且不会发生任何延续。

2)即使您启动任务,也无法保证任务将及时完成条件检查..这就是为什么Task.ContinueWith有一个接受TaskContinuationOptions枚举的重载...你有OnlyOnRanToCompletion,OnlyOnFaulted等等。

3)总结一下,经过一番微调后,这是你的代码

  for (int i = 0; i < _paralellTaskCount; i++)
        {
            object message;
            int counter = CheckCounter(message);

            if (counter >= 0)
            {
                var task = Task.Run(() => CalcSingle(_personnelIds[counter].Item1));
                var continuation = task.ContinueWith((antecedent) => CalcSingle(_personnelIds[counter].Item1),
                    TaskContinuationOptions.OnlyOnRanToCompletion);

            }
        }

(注意,继续接收先行任务,这是它继续的任务..

4)您似乎没有检查任何任务中是否发生异常,提供的方法有多种。请注意,在try catch子句中包装语句不会将异常传递给您的线程..(您需要访问Result或Exception属性,调用Wait()或使用await关键字来实现它。

5)这是一个异步实现,它执行相同的操作,并检查异常

 for (int i = 0; i < _paralellTaskCount; i++)
        {
            try
            {
                object message;
                int counter = CheckCounter(message);

                if (counter >= 0)
                {
                    long res1 = await Task.Run(() => CalcSingle(_personnelIds[counter].Item1));
                    long res2 = await Task.Run(() => CalcSingle(_personnelIds[counter].Item1));
                }
            }
            catch (AggregateException e)
            {
                //TODO handle
            }
        }

6)请阅读一些关于TPL的文章,因为您似乎错过了一些非常重要的概念。