CancellationTokenSource cts = new CancellationTokenSource();
List<Task> allTask = new List<Task>();
for (int i = 0; i < 10000; i++)
{
int j = i;
allTask.Add(Task.Factory.StartNew(() =>
{
if (cts.Token.IsCancellationRequested)
{
return;
}
cts.Cancel();
Thread.Sleep(1000);
Console.WriteLine("I'm doing it");
}, cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Current));
}
Task.WaitAll(allTask.ToArray());
Console.WriteLine("Implementation success!");
Console.ReadKey();
对于问题,取消任务后,我的程序无法继续运行。这是为什么?我显然取消了。
为什么我的程序没有输出"Implementation success"
?
答案 0 :(得分:0)
这是设计使然;调用cts.Cancel()
总是会在TaskCanceledException
调用中抛出WaitAll
。因此,您的代码将1000个任务排队,等待所有工作,引发异常,程序终止。
签出TPL文档https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-cancel-a-task-and-its-children#example明确告诉您如何通过使用AggregateException
处理程序检查TaskCancelledException
中的InnerExceptions
来处理这种情况。
如果希望您的代码通过正确的取消操作进入“实施成功”,则添加一个AggregateException
处理程序:
CancellationTokenSource cts = new CancellationTokenSource();
List<Task> allTask = new List<Task>();
for (int i = 0; i < 10000; i++)
{
int j = i;
allTask.Add(Task.Factory.StartNew(() =>
{
if (cts.Token.IsCancellationRequested)
{
return;
}
cts.Cancel();
Thread.Sleep(1000);
Console.WriteLine("I'm doing it");
}, cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Current));
}
try
{
Task.WaitAll(allTask.ToArray());
}
catch (AggregateException ex)
{
//handle the cancelled tasks here, though you are doing it on purpose...
Console.WriteLine("One or more tasks were cancelled.");
}
Console.WriteLine("Implementation success!");
Console.ReadKey();
答案 1 :(得分:0)
我有类似的问题,我的任务工作时间太长,并按以下方式解决: 在xxx类中,我有私人收藏:
private List<TaskWork> _taskCollection = new List<TaskWork>();
将新任务添加到列表:
var cancellationToken = new CancellationTokenSource();
cancellationToken.CancelAfter(10000);
var taskWork = new TaskWorkVM
{
CancellationToken = cancellationToken.Token,
StartTime = DateTime.Now
};
taskWork.Task = Task.Run(() => { [some_work]; }, taskWork.CancellationToken);
_taskCollection.Add(taskWork);
检查任务是否已完成,并从集合中删除:
var completedTask = _taskCollection.Where(t => t.Task.IsCompleted).FirstOrDefault();
if (completedTask != null)
{
_taskCollection.Remove(completedTask);
}
您可以在检查清单的同时执行操作,我认为只要简单就可以:
while (_taskCollection.Count() > 0)
{
//do something
}
任务类具有olso标志IsCanceled或您可以使用任务状态。