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;
}
在上面的代码块中,我想运行Canceled
和Completed
的任务,但它不起作用。
我的错是什么?
答案 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的文章,因为您似乎错过了一些非常重要的概念。