来自 Task.Run 的抛出异常显示 "Not Handled from User Code" 消息

Throwing exception from Task.Run displays "Not Handled from User Code" Message

代码示例:

using System;
using System.Threading.Tasks;

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Start");
        Foo f = new Foo();
        f.FooAsync();
    }

    public class Foo
    {
        public async void FooAsync()
        {
            try
            {
                await Task.Run(() =>
                {
                    Console.WriteLine("Throwing");
                    throw new Exception();
                });
            }
            catch (Exception)
            {
                Console.WriteLine("Caught");
            }
        }
    }
}

当 运行 从 C# fiddle 或从我的 PC 上的控制台打印时,上面的代码:

Start
Throwing
Caught

C# Fiddle Example

但是,当我从 Visual Studio(调试模式下的 F5)运行 时,我收到以下消息:

我不明白为什么我从 Visual Studio 收到 "was not handled in user code" 消息,尽管 运行 从控制台或 C# fiddle 可以正常。我是否漏掉了一些明显的东西?

更新

我已经尝试在 Main 中等待任务 f.FooAsync().Wait();,但仍报告异常未处理(相同的错误消息)。

首先,此异常的特别之处在于它是从 Task.Run 中抛出的,并且对于该范围,该异常实际上并未由用户代码处理

框架捕获异常并将其存储在返回的任务中供您稍后处理,如果您未能做到这一点,则它是一个未观察到的任务异常(在 .Net 4.0 中会导致应用程序崩溃)。

这里的问题是设置中的"Enable Just My Code"功能。启用该功能后,当您离开用户代码并输入框架代码时,调试器会因异常而中断,此时异常实际上并未得到处理。

如果您关闭该功能,调试器将不会中断该异常,因为它会跟随您的代码进入框架并查看正在处理的异常并将其存储在任务中。当您 await 任务并由您的代码处理时,异常将被重新抛出。


由于真正重要的处理是由框架完成的,这是一个更简单的示例:

public static void Main()
{
    Task.Run(() =>
    {
        throw new Exception();
    });
    Console.ReadLine();
}

启用 "Enable Just My Code" 后,调试器将在出现异常时中断,否则调试器将不会。