【问题标题】:Handling exceptions thrown in a canceled Task处理取消的任务中抛出的异常
【发布时间】:2013-10-24 02:34:36
【问题描述】:

我正在研究Exam Ref 70-483: Programming in C# 书中的示例,并遇到了清单 1-44 中的以下代码的问题。在这个例子中,作者试图证明一个延续任务可以访问在前面的任务中抛出的未处理的异常,并且可以在适当的时候处理它们。

static void Main(string[] args)
{
    CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
    CancellationToken token = cancellationTokenSource.Token;

    Task task = Task.Run(() =>
    {
        while (!token.IsCancellationRequested)
        {
            Console.Write("*");
            Thread.Sleep(1000);
        }
        throw new OperationCanceledException();
    }, token).ContinueWith((t) =>
    {
        t.Exception.Handle((e) => true);
        Console.WriteLine("You have canceled the task.");
    }, TaskContinuationOptions.OnlyOnCanceled);

    Console.WriteLine("Press enter to stop the task.");
    Console.ReadLine();

    cancellationTokenSource.Cancel();
    task.Wait();

    Console.WriteLine("Press enter to end the application.");
    Console.ReadLine();
}

不幸的是,这行代码在继续

t.Exception.Handle((e) => true);

抛出异常,因为 t.Exceptionnull

在该行设置断点,我可以看到t.StatusCanceled,而不是Faulted。这就是为什么异常不可用的原因吗?处理前面任务中抛出的异常的正确方法是什么?

【问题讨论】:

    标签: c# task-parallel-library


    【解决方案1】:

    使用

    task.ContinueWith(HandleError, TaskContinuationOptions.OnlyOnFaulted);
    

    取消的任务并非例外...因此不会包含例外。有缺陷的人会。

    【讨论】:

    • 那么,如果我想保留延续选项OnlyOnCanceled,那么处理该异常的唯一方法是在第一个任务中?
    • @adrift,不。您可以添加另一个延续,即OnlyOnFaulted
    • @MattSmith 第二个延续捕获第一个延续中抛出的空引用异常,而不是原始任务中抛出的异常。如果我在第一个延续中注释掉有问题的行,则永远不会输入第二个延续。这是有道理的,因为它是第一个延续的延续。
    • @adrift,不要在延续上做延续——在原始任务上做它(即在第一个任务上添加两个延续:一个用于故障,一个用于取消)。在“取消”中,不要查看 Exception 属性,因为您知道它将为空。查看故障延续中的异常属性。
    【解决方案2】:

    将示例 1-44 的代码更改为:

    Task task = Task.Run(() => { 
        while (true) 
        {
         token.ThrowIfCancellationRequested();
         Console.Write("*");
         Thread.Sleep(1000); }
        }, token).ContinueWith(t =>
     { Console.WriteLine("You have canceled the task"); }, TaskContinuationOptions.OnlyOnCanceled);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-05
      • 1970-01-01
      • 2016-01-06
      • 1970-01-01
      相关资源
      最近更新 更多