首页 > 解决方案 > 任务在运行时被取消,我的程序无法继续运行

问题描述

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"

标签: c#asynchronoustask-parallel-library

解决方案


这是设计使然;调用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();

推荐阅读