2014-02-19 171 views
2

我的应用程序具有全局异常处理程序(好吧,伐木工,我知道他们在技术上不“处理”它们),这仅仅是这样的:未处理的异常未被捕获/处理

public static class UnhandledExceptionHandler 
{ 
    public static void Init() 
    { 
     AppDomain.CurrentDomain.UnhandledException += OnCurrentDomainOnUnhandledException; 

     Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); 
     Application.ThreadException += ApplicationOnThreadException; 
    } 

    private static void ApplicationOnThreadException(object sender, ThreadExceptionEventArgs e) 
    { 
     if (e.Exception != null) 
      MessageBox.Show(e.Exception.ToString()); 
    } 

    private static void OnCurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs e) 
    { 
     var ex = e.ExceptionObject as Exception; 

     if (ex != null) 
      MessageBox.Show(ex.ToString()); 
    } 
} 

Main()

UnhandledExceptionHandler.Init(); 

但我发现,当未处理的异常,一个Task.ContinueWith内发生这些事件不会引发。 Visual Studio将它们识别为未处理,因为它们在调试器中突出显示。

例如,你可以用简单的测试:

private void button1_Click(object sender, EventArgs e) 
{ 
    Task.Factory.StartNew(() => { }) 
    .ContinueWith(t => 
    { 
     throw new Exception("continue with exception"); 
    }); 
} 

你会发现,任何的MessageBox得到提高(也不是复活了的事件)。

只是为了证明它的工作,下面的工作:

private void button2_Click(object sender, EventArgs e) 
{ 
    throw new Exception("click failed"); 
} 

任何人有任何想法,为什么和/或我如何能够捕捉并记录这些未处理的异常?

当然,我很欣赏将ContinueWith中的逻辑数量保持在最小值,但它仍然可能会发生。

这是目前.NET 4.0

+0

'Task.Factory.StartNew/ContinueWith'返回一个具有* Exception *属性的任务。 –

+0

好吧,但这不意味着在我上面的例子中,那么我将不得不有**另一** ContinueWith,然后我检查't.Exception'?那么我会需要一个无限数量的ContinueWith以防万一:) – OffHeGoes

+0

写入无限数量的ContinueWiths只有在您认真对待用户名时才有意义。使用承担TaskContinuationOptions.OnlyOnFaulted的重载往往很有用。避免编写遗忘代码。 –

回答

1

从评论:

这是一个耻辱,虽然我有追加与 一个ContinueWith为了OnlyOnFaulted到任务的任何其他ContinueWiths后 保证我处理异常。

您不需要。请使用"Processing Sequences of Asynchronous Operations with Tasks"的Stephen Toub的Then模式。另外,请务必阅读"Tasks and Unhandled Exceptions",这将有助于更好地了解您所看到的行为。

也就是说,如果您使用VS2012 +进行编码,您可能需要认真考虑使用Microsoft.Bcl.Asyncasync/await。这会让你忘记ContinueWith,并使用自然try/catch来处理异常。

+1

虽然这并没有回答我的问题,但这真的有助于理解'ContinueWith'返回** new ***'Task'的方式,当与'OnlyOnFaulted'组合时仅在失败时执行。因此,链接这些“ContinueWith”的行为并不像预期的那样。 – OffHeGoes