【问题标题】:Exception in async task gets intercepted in Visual Studio异步任务中的异常在 Visual Studio 中被拦截
【发布时间】:2015-08-31 02:31:55
【问题描述】:

我想运行几个任务,其中一些会异步完成,然后等待它们全部完成。由于任务可能引发异常,我想捕获并记录它们。示例代码:

static async Task doit(int x)
{
    try
    {
        Console.WriteLine("{0}  {1}  start", x, Thread.CurrentThread.ManagedThreadId);
        await Task.Run(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(2 + x));  // simulate long-running stuff worth awaiting...
            if (x == 3)
            {
                throw new Exception("Exception inside task " + x.ToString());  // Simulate the async task throwing exception
            }
        });

        if (x == 2)
        {
            throw new Exception("Exception after task " + x.ToString());  // Simulate post-async task throwing exception
        }

        Console.WriteLine("{0}  {1}  end", x, Thread.CurrentThread.ManagedThreadId);
    }
    catch (Exception ex)
    {
        Console.WriteLine("{0}  {1}  Exception: {2}", x, Thread.CurrentThread.ManagedThreadId, ex.Message);
    }
}

private static void TestTasks()
{
    var tasks = Enumerable.Range(1, 3).Select(n => doit(n)).ToArray();
    Console.WriteLine("Waiting");
    Task.WaitAll(tasks);
    Console.WriteLine("all end");
}

如果我从控制台运行此代码,它会按预期工作,并带有以下输出:

1  1  start
2  1  start
3  1  start
Waiting
1  3  end
2  4  Exception: Exception after task 2
3  5  Exception: Exception inside task 3
all end

但是,如果我在 Visual Studio 中进行调试,调试器会在Exception was unhandled by user code 出现的异常处停止。然后我需要点击F5 Continue 来完成代码。

我注意到如果我禁用 Options => Debugger => Enable Just My Code,调试器不会停止。但是,我不想永久设置它,因为我使用的一些框架会处理我确实希望调试器停止的异常。

  • 为什么即使异常在 try/catch 中,调试器也会停止?
  • 如何让调试器在此异常处不停止?

【问题讨论】:

  • Debug -> Start without debugging怎么样?
  • @Mike:当然可以,但我确实想设置断点。
  • 不确定它是否会这样做,但尝试使用[DebuggerStepThrough] 属性装饰doit(int x)。副作用是方法中的断点也不起作用。不确定在这种情况下您是否也可以吃蛋糕。
  • @Ron:不,不会改变情况。

标签: c# visual-studio exception asynchronous


【解决方案1】:

为什么即使异常在 try/catch 中,调试器也会停止?

从技术上讲,该代码正在引发一个异常,该异常未被当前调用堆栈上的任何您的代码捕获。它被(编译器生成的)async 状态机捕获并放置在返回的任务上。稍后,当从Task.Run 返回的任务是awaited 时,重新抛出该异常。

如何让调试器在这个异常处不停止?

现在,您唯一的选择是让调试器以某种方式忽略此异常(仅禁用我的代码,禁用中断该类型的用户未处理的异常,...)。

如果您认为 VS 应该在这里提供更好的用户体验,请随时提出 uservoice 建议。

【讨论】:

【解决方案2】:

为什么即使异常在 try/catch 中,调试器也会停止?

这种行为显然取决于 Visual Studio 的版本。

我在 Visual 2013 中遇到了同样的问题。我尝试使用 Visual 2015 Update 1 构建和调试相同的代码。这一次,调试器正确处理了异常并且没有停止。

您没有提及您使用的是哪个版本的 Visual。如果是 2015 年以前的版本,您可以尝试使用 Visual 2015 或更新版本,看看它是否能解决问题。

【讨论】:

  • 在 Visual Studio 2017 15.9.12 中仍然发生。
猜你喜欢
  • 2022-08-04
  • 1970-01-01
  • 1970-01-01
  • 2010-09-18
  • 1970-01-01
  • 2015-10-03
  • 2013-05-31
  • 1970-01-01
  • 2012-09-27
相关资源
最近更新 更多