【问题标题】:Task Parallel Library exception handling任务并行库异常处理
【发布时间】:2012-09-18 20:08:40
【问题描述】:

在 TPL 任务中处理异常时,我遇到了两种处理异常的方法。第一个捕获任务中的异常并在结果中返回它,如下所示:

var task = Task<Exception>.Factory.StartNew(
    () =>
        {
            try
            {
                // Do Something

                return null;
            }
            catch (System.Exception e)
            {
                return e;
            }
        });

task.ContinueWith(
    r =>
        {
            if (r.Result != null)
            {
                // Handle Exception
            }
        });

第二个是文档中显示的,我猜是做事的正确方法:

var task = Task.Factory.StartNew(
    () =>
        {
            // Do Something
        });
task.ContinueWith(
    r =>
        {
            if (r.Exception != null)
            {
                // Handle Aggregate Exception
                r.Exception.Handle(y => true);
            }
        });

我想知道第一种方法是否有问题? 我使用这种技术时常收到“未处理的聚合异常”异常,想知道这是怎么发生的?

澄清一下,我认为第二种模式更好,但我有一大段代码使用第一种模式,我试图找出它是否需要重构,即如果事实证明不是全部异常会被捕获。

【问题讨论】:

  • 我遇到了同样的问题,虽然我检查了 task.IsFaulted,但我发现如果它在任务期间出现异常,即使我做的第一件事是检查它,并注意到它并放弃,它仍然引起问题..我得到了一个不应该有的异常泄漏..

标签: c# .net task-parallel-library


【解决方案1】:

第一种方法假定每次调用都会引发异常。虽然这可能是真的,但这些异常似乎并不“异常”,而且有设计问题的味道。如果异常不是异常,那么结果就没有多大意义。另一个问题是,如果你确实想要一个“结果”(即Exception 以外的东西),你不能因为Result 插槽用于Exception。另一个问题是您没有在主线程上重新抛出异常(您可以手动执行此操作),因此您没有获得 catch 语义(即您使用的是 Handle 方法)。

第二种方法会被更多人更好地理解。

【讨论】:

  • 感谢您的 cmets。我在预期会出现异常(数据库访问)的存储库中使用这种方法。如果我需要返回结果,我有一个 RepositoryResult 类,该类可以由任务返回并包含结果和异常。任务继续是发生异常处理的地方(即调用异常处理服务)。我真正想知道的是,如何使用第一种方法得到未处理的聚合异常?
  • 因此,您处理异常的方式会不一致。并不是说TaskTask&lt;T&gt; 具有一致的方式,因为缺少 Result 属性,但已经有 Task.Exception 属性以及 IsFaulted...
  • 我同意,第二种方法更好。不幸的是,我已经编写了一些大量使用第一个模式的代码,现在我需要决定是否有必要返回并重新考虑它 - 因此问题是第一个模式是否会导致未处理的聚合异常。
  • 我认为第二种方法更易于维护;但是,如果其他代码有效,则可能没有理由对其进行重构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
  • 2018-07-19
  • 2014-03-06
相关资源
最近更新 更多