为什么引发异常时应用程序不会崩溃

时间:2018-06-26 11:06:25

标签: c# multithreading async-await task-parallel-library

在WPF应用中,我添加了两个按钮,一个按钮启动一个Task,另一个按钮强制GC运行:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Task.Run(() =>
        {
            throw new Exception("Some Exception");
        });
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }

任务只是引发异常。

在Release config中运行该应用程序时,我先按第一个按钮,然后按第二个按钮,并期望该应用程序崩溃。无论我按几次按钮,都不会发生这种情况。

我知道.NET 4.5中存在无法观察的任务吞没异常的行为:https://blogs.msdn.microsoft.com/pfxteam/2011/09/28/task-exception-handling-in-net-4-5/

但是我感到困惑的是,为什么一旦GC运行,应用程序就不会崩溃。根据我的理解,一旦任务被收集,就应该抛出信号。

还请注意,我知道这个问题无法回答我的问题 Why doesn't my process terminate when Task has unhandled exception?

标记为答案的评论建议使用ContinueWith,但这也不起作用,应用程序也不会崩溃,但吞没了异常:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Task.Run(() =>
        {
            throw new Exception("Some Exception");
        }).ContinueWith(t =>
        {
            if (t.IsFaulted) { throw t.Exception.InnerException; }
        });
    }

我已经知道等待任务会导致应用崩溃。

2 个答案:

答案 0 :(得分:5)

这是因为您开枪而忘记了。异常将在单独的线程中发生。如果您希望它崩溃,则必须await或使其同步。

private void Button_Click(object sender, RoutedEventArgs e)
{
    await Task.Run(() =>
    {
        throw new Exception("Some Exception");
    });
}

答案 1 :(得分:4)

  

但是我感到困惑的是,为什么一旦GC运行,应用程序就不会崩溃。根据我的理解,一旦任务被收集,就应该抛出信号。

您的理解是正确的,前提是您通过在1中添加以下元素来使用旧的行为(.NET Framework 4.5之前的版本):

Foo::where('bar', function($query) {
    $query->fromBaz(1);
});

如果您不这样做,App.config不会导致进程崩溃。但是仍然会引发异常,因此您可以在两种情况下都处理<runtime> <ThrowUnobservedTaskExceptions enabled="true"/> </runtime> 事件。