在ContinueWith中引发的未处理异常未在全局处理程序中捕获/处理

时间:2014-02-19 11:29:49

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

我的应用程序有全局异常处理程序(好吧,记录器,我知道它们在技术上并没有“处理”它们),这些就像是:

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.Continue中发生未处理的异常时,不会引发这些事件。 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

1 个答案:

答案 0 :(得分:1)

来自评论:

  

虽然我必须追加一个ContinueWith,但这是一种耻辱   在任何其他的ContinueWith之后,只有OnOnFaulted到任务   确保我处理异常。

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

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