如何处理Task.Factory.StartNew异常?

时间:2014-04-04 07:14:27

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

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

我试试这个:

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)
            {

            }
        });

2 个答案:

答案 0 :(得分:7)

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

这并不意味着你的异常真的未处理。它只是意味着,默认情况下,Visual Studio会对未在任务内部处理的异常进行分解。您可以通过运行应用程序而无需调试来验证这一点(Ctrl-F5);你会注意到你的异常按预期处理。

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

答案 1 :(得分:3)

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

但实际上现在" Just My Code"功能会干扰TPL实施。

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

  1. 无需调试即可运行代码。
  2. 通过继续执行程序,忽略有关无法处理的异常的Visual Studio调试器消息。
  3. 禁用" Just My Code" Microsoft Visual Studio中的选项。这个变种是来自Parallel Computing Platform团队(PFX团队)的微软家伙Danny Shih http://blogs.msdn.com/b/pfxteam/archive/2010/01/11/faq-the-debugger-does-not-correctly-handle-task-exceptions.aspx推荐的。