从Task.Run抛出异常会显示“Not Notled from User Code”消息

时间:2015-06-06 07:30:49

标签: c# .net async-await task-parallel-library

代码示例:

false

以上代码从C#小提琴运行或从我PC上的控制台运行时打印:

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 Example

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

Exception Picture

我不明白为什么我从Visual Studio中获取“未在用户代码中处理”消息,尽管从控制台或C#小提琴运行它是好的。我错过了一些明显的东西吗?

更新

我已经尝试等待Main中的任务Start Throwing Caught ,但仍然报告该异常未处理(相同的错误消息)。

1 个答案:

答案 0 :(得分:10)

首先,这个异常的特殊之处在于它是从Task.Run抛出的,对于该范围,异常实际上不是由用户代码处理

框架捕获并将异常存储在返回的任务中供您稍后处理,如果您没有这样做,那么这是一个未被观察到的任务异常(在.Net 4.0中会使应用程序崩溃)。

此处的问题是“设置中的”启用我的代码“功能。当打开该功能时,调试器会在您离开用户代码并输入框架代码时中断异常,此时实际上未处理异常。

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

由于实际上重要的处理是由框架完成的处理,这是一个更简单的例子:

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

启用“启用我的代码”后,调试器将在异常中断,没有它,调试器就不会。