如何处理 Task.Factory.StartNew 异常

本文关键字:Task Factory StartNew 异常 处理 何处理 | 更新日期: 2023-09-27 17:56:48

我这里有一些奇怪的问题。任务引发的异常总是不能独立处理,我该如何尝试处理它。

我试试这个:

http://msdn.microsoft.com/en-us/library/dd997415%28v=vs.110%29.aspx

private class MyCustomException : Exception
{
     public MyCustomException(String message) : base(message)
     {
     }
}
public static void Main()
{
   var task1 = Task.Factory.StartNew(() =>
   {
      throw new MyCustomException("I'm bad, but not too bad!");
   });
   try
   {
      task1.Wait();
   }
   catch (AggregateException ae)
   {
       // Assume we know what's going on with this particular exception. 
       // Rethrow anything else. AggregateException.Handle provides 
       // another way to express this. See later example. 
       foreach (var e in ae.InnerExceptions)
       {
           if (e is MyCustomException)
           {
               Console.WriteLine(e.Message);
           }
           else
           {
               throw;
           }
       }
    }
    Console.Read();
}

这:

http://dotnetcodr.com/2014/02/11/exception-handling-in-the-net-task-parallel-library-with-c-the-basics/

这:

http://blogs.msdn.com/b/pfxteam/archive/2010/08/06/10046819.aspx

这:

var task = Task.Factory.StartNew(() => this.InitializeViewModel(myViewModel));
task.ContinueWith(o => MyErrorHandler(task.Exception), TaskContinuationOptions.OnlyOnFaulted);

并在StackOverflow上检查许多其他类似的问题。但它总是相同的 - 不处理异常。它不会在这些原始代码片段上处理!我认为这是一些魔力...我在.Net Framework 4.0上工作

同时,处理对我有用的异常的单一方法是:

        Task.Factory.StartNew(() =>
        {
            try
            {
                //do something that thrown exception
            }
            catch (Exception)
            {
            }
        });

如何处理 Task.Factory.StartNew 异常

如果你在Visual Studio中运行该示例代码,你确实会得到消息MyCustomException was unhandled by user code Visual Studio将在该行中断。

这并不意味着您的异常确实未处理。这只是意味着,默认情况下,Visual Studio会中断任务未处理的异常。可以通过在不调试的情况下运行应用程序来验证这一点 (Ctrl-F5);您会注意到您的异常会按预期处理。

以下 SO 问题更详细地描述了此问题:

  • 阻止视觉工作室在任务中出现异常时中断

Microsoft托管代码的Visual Studio调试工具有一个选项"Just My Code"。启用此选项强制调试器在异常离开用户代码(示例中为任务委托)并输入非用户代码(示例中为 TPL 内部)时立即中断。此功能是在引入 TPL 之前设计的,目的是使 .NET 应用程序调试更适应仅查看已编写的代码而忽略其他代码(如系统调用)。"仅我的代码"隐藏非用户代码,使其不会出现在调试器窗口中。单步执行时,调试器将单步执行任何非用户代码,但不会在其中停止。

但现在实际上"只是我的代码"功能会干扰TPL的实现。

有四种方法可以解决此问题:

  1. 在不调试的情况下运行代码。
  2. 只是忽略Visual Studio调试器消息,通过继续程序执行来传递未处理的异常。
  3. 在Microsoft Visual Studio中禁用"Just My Code"选项。这个变体是由并行计算平台团队(PFX团队)http://blogs.msdn.com/b/pfxteam/archive/2010/01/11/faq-the-debugger-does-not-correctly-handle-task-exceptions.aspx 的Microsoft Danny Shih推荐的。