调试器不会因异步方法中的异常而中断/停止

Posted

技术标签:

【中文标题】调试器不会因异步方法中的异常而中断/停止【英文标题】:Debugger not breaking/stopping for exceptions in async method 【发布时间】:2013-08-07 17:50:21 【问题描述】:

当调试器附加到 .NET 进程时,它(通常)会在引发未处理的异常时停止。

但是,当您使用 async 方法时,这似乎不起作用。

我之前尝试过的场景如下代码:

class Program

    static void Main()
    
        // Debugger stopps correctly
        Task.Run(() => SyncOp());

        // Debugger doesn't stop
        Task.Run(async () => SyncOp());

        // Debugger doesn't stop
        Task.Run((Func<Task>)AsyncTaskOp);

        // Debugger stops on "Wait()" with "AggregateException"
        Task.Run(() => AsyncTaskOp().Wait());

        // Throws "Exceptions was unhandled by user code" on "await"
        Task.Run(() => AsyncVoidOp());

        Thread.Sleep(2000);
    

    static void SyncOp()
    
        throw new Exception("Exception in sync method");
    

    async static void AsyncVoidOp()
    
        await AsyncTaskOp();
    

    async static Task AsyncTaskOp()
    
        await Task.Delay(300);
        throw new Exception("Exception in async method");
    

我错过了什么吗?如何使调试器中断/停止AsyncTaskOp() 中的异常?

【问题讨论】:

你解决过这个问题吗? @RichardSzalay 不,很遗憾没有。我想我只是习惯了这个。 您可能想为此投票给 uservoice:visualstudio.uservoice.com/forums/121579-visual-studio-ide/… “此 UserVoice 实例不再可用。” 【参考方案1】:

我想知道是否有人知道如何解决这个问题?也许是最新视觉工作室中的设置...?

一个讨厌但可行的解决方案(就我而言)是抛出我自己的 custom 异常,然后修改 Stephen Cleary 的答案:

在“调试”菜单下,选择“例外”(您可以使用此键盘快捷键 Control + Alt + E)...在 Exceptions 对话框中,在 Common Language Runtime Exceptions 行旁边检查 Throw 盒子。

更具体地说,将您的自定义异常添加到列表中,然后勾选其“抛出”框。

例如:

async static Task AsyncTaskOp()

    await Task.Delay(300);
    throw new MyCustomException("Exception in async method");

【讨论】:

如果Task.Delay() 抛出不同的异常会发生什么? Thomas,我只是在扩展原始发帖人的示例。脱离你的逻辑,anything 可能会失败 - 这是真的,但我们必须在上下文中回答,......所以我们可以永远绕圈子......我的回答是在上下文中调试器在代码中的一个理想点停止,然后您可以查看局部变量值是什么以及可能导致异常的原因。如果异常是在任务之外抛出的(根据 OP),这不容易实现,因为它可能成为调试的噩梦。【参考方案2】:

我已将匿名委托包装在 Task.Run(() =&gt; 内的 try/catch 中。

Task.Run(() => 

     try
     
          SyncOp());
     
     catch (Exception ex)
     
          throw;  // <--- Put your debugger break point here. 
                  // You can also add the exception to a common collection of exceptions found inside the threads so you can weed through them for logging
     

);

【讨论】:

没有帮助,因为这样调试器会在异常被捕获的位置中断 - 而不是抛出的位置。 有助于查看实际的异常细节,在大多数情况下就足够了。【参考方案3】:

Debug 菜单下,选择Exceptions...。在“例外”对话框中,在 Common Language Runtime Exceptions 行旁边选中 Thrown 框。

【讨论】:

好的,我确实知道。但是调试器会在 all 异常上中断,而不仅仅是在未处理的异常上,对吗?所以这不是我想要的。 @SebastianKrysmanski:不过,异常已得到处理。如果你有一个async Task 方法,那么异常会被async 状态机捕获并放在返回的Task 上。 在Visual Studio 2015中,异常设置位于Debug >> Windows >> Exception Settings (Ctrl+Alt+E) @StephenCleary “虽然异常已处理。” - 是的,但它没有被用户代码捕获。即使启用了“仅我的代码”,它仍然认为异步管道中的隐式 catch 不应该被视为用户代码。

以上是关于调试器不会因异步方法中的异常而中断/停止的主要内容,如果未能解决你的问题,请参考以下文章

FireBug 1.7.3 不会因任何错误而中断,在继续之后,甚至是“调试器”语句

NetBeans PHP 不会因异常而中断

远程调试不会因错误而中断

Visual Studio 不会因用户未处理的异常而中断

防止 VS C# 单元测试因异常而中断

启用“仅我的代码”时,Visual Studio 2015 JavaScript 调试不会捕获未处理的异常