【问题标题】:Unhandled Exception raised in ContinueWith not caught/handled in global handler在 ContinueWith 中引发的未处理异常未在全局处理程序中捕获/处理
【发布时间】:2014-03-19 16:54:58
【问题描述】:

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

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

【问题讨论】:

  • Task.Factory.StartNew/ContinueWith 返回一个具有 Exception 属性的任务。
  • 好的,但这不意味着在我上面的例子中我必须有 另一个 ContinueWith 然后我检查t.Exception?那么我是否需要无限数量的 ContinueWith 以防万一:)
  • 只有当您过于认真地对待您的用户名时,编写无限数量的 ContinueWiths 才有意义。使用采用 TaskContinuationOptions.OnlyOnFaulted 的重载往往很有用。请避免编写即发即弃的代码。
  • 很遗憾,我必须将带有 OnlyOnFaulted 的 ContinueWith 添加到 Task 之后 任何其他 ContinueWiths 以确保我处理异常。

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


【解决方案1】:

来自cmets:

很遗憾,我必须附加一个 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 来处理异常。

【讨论】:

  • 虽然这不能回答我的问题,但这确实有助于理解 ContinueWith 返回 new* Task 的方式,当与 OnlyOnFaulted 结合使用时仅在失败时执行。因此,链接这些 ContinueWiths 的行为并不符合预期。
猜你喜欢
  • 2018-06-14
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
  • 2011-07-02
  • 1970-01-01
  • 2015-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多