【问题标题】:Throwing exception from Task.Run displays "Not Handled from User Code" Message从 Task.Run 引发异常显示“未从用户代码处理”消息
【发布时间】:2015-06-06 07:30:49
【问题描述】:

代码示例:

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 收到“未在用户代码中处理”消息,尽管从控制台或 C# fiddle 运行它很好。我错过了什么明显的东西吗?

更新

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

【问题讨论】:

  • 代码没问题,是你的调试器设置错误。单击“打开异常设置”链接,取消选中“抛出”复选框。如果您有意打开它,只需点击继续。
  • @HansPassant:谢谢。我找到了more info about the problem here also

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


【解决方案1】:

首先,这个异常的特别之处在于它是从Task.Run 抛出的,并且对于那个范围,这个异常确实不是由用户代码处理

框架会捕获异常并将其存储在返回的任务中以供您稍后处理,如果您未能执行此操作,则它是未观察到的任务异常(在 .Net 4.0 中会使应用程序崩溃)。

这里的问题是设置中的“仅启用我的代码”功能。打开该功能后,当您离开用户代码并输入框架代码时,调试器会中断异常,此时该异常确实没有得到处理。

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


因为真正重要的处理是由框架完成的,所以这是一个更简单的例子:

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

启用“仅启用我的代码”后,调试器会因异常而中断,否则调试器不会。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-24
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多