任务正在运行时被取消,我的程序无法继续运行

时间:2018-08-01 01:56:35

标签: c# asynchronous task-parallel-library

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"

2 个答案:

答案 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或您可以使用任务状态。