【问题标题】:TPL and Exception HandlingTPL 和异常处理
【发布时间】:2012-04-10 20:06:13
【问题描述】:

所有,关于上述主题有很多问题,但我相信这有足够的不同,需要提出一个新问题。我有以下Task和一个继续处理各种任务StatusTaskStatus.RanToCompletionTaskStatus.Canceled,当然还有AggregateExceptionTaskStatus.Faulted。代码看起来像

Task<bool> asyncTask = Task.Factory.StartNew<bool>(() =>
    asyncMethod(uiScheduler, token, someBoolean), token);

asyncTask.ContinueWith(task =>
{
    // Check task status.
    switch (task.Status)
    {
        // Handle any exceptions to prevent UnobservedTaskException.             
        case TaskStatus.RanToCompletion:
            if (asyncTask.Result)
            {
                // Do stuff...
            }
            break;
        case TaskStatus.Faulted:
            if (task.Exception != null)
                mainForm.progressRightLabelText = task.Exception.InnerException.Message;
            else
                mainForm.progressRightLabelText = "Operation failed!";
        default:
            break;
    }
}

这一切都很好,但我担心我是否做对了,因为有可能从延续中抛出AggregateException - 然后呢?

我不想在我的asyncTaskWait 也不想继续,因为这会阻止返回到 UI 线程。捕获从延续中抛出的任何异常并不意味着我必须肯定地做这样的事情

Task parentTask = Task.Factory.startNew(() => 
    {
        Task<bool> asyncTask = Task.Factory.StartNew<bool>(() =>
            asyncMethod(uiScheduler, token, someBoolean), token);

        Task continueTask = asyncTask.ContinueWith(task =>
            {
                // My continuation stuff...   
            }

        try
        {
            continueTask.Wait();
        }
        catch(AggregateException aggEx)
        { 
            // Some handling here...
        }
    });

这还能用吗?这里的最佳做法是什么?

一如既往,感谢您的宝贵时间。

【问题讨论】:

  • 我见过“跑到完成”的任务,实际上它们抛出了 AggregateException。这种错误处理是行不通的。为什么不直接使用 try/catch?
  • 你的意思是在后台线程调用的方法中,还是在实际的延续委托方法中?

标签: c# exception-handling task-parallel-library continuations


【解决方案1】:

可以在您的代理中使用传统的 try/catch 来监视AggregateException,或者您可以链接特定的延续,这些延续只有在使用TaskContinuationOptions.OnlyOnFaulted 选项出现故障时才会运行。后一种方法允许定义非常干净的任务工作流。例如:

Task myRootTask = ....;

myRootTask.ContinueWith(rootAntecdent =>
{
    // this will only be executed if the antecedent completed successfully, no need to check for faults
},
TaskContinuationOptions.OnlyOnRanToCompletion);

myRootTask.ContinueWith(rootAntecedent =>
{
    // this will only be executed if the antecedent faulted, observe exception and handle accordingly
},
TaskContinuationOptions.OnlyOnFaulted);

【讨论】:

    【解决方案2】:

    Msdn 关于这个主题的“如何”写得相当好:here

    您会注意到他们只是使用try/catch(AggregateException) 块,然后在ae.Handle(lambda) 中过滤他们知道如何处理的异常,并在有一些无法处理的情况下停止应用程序。

    【讨论】:

    • 我知道您的链接提供的示例,并且 以这种方式 处理接收没有问题。我的问题是如何处理从延续引发的异常而不用 try catch 封闭整个延续委托,那么这可能是唯一的方法。我想知道真实世界代码的最佳实践,而不是微软玩具代码的最佳实践。干杯。
    • OP 想知道如何在不使用 Wait 的情况下执行此操作。示例全部等待任务。试试这个[msdn.microsoft.com/en-us/library/dd997415.aspx]链接。
    猜你喜欢
    • 2012-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    相关资源
    最近更新 更多