【问题标题】:How to ignore a specific Exception INSTANCE for an async method in Visual Studio (break on thrown)如何在 Visual Studio 中忽略异步方法的特定异常实例(抛出时中断)
【发布时间】:2017-05-20 22:51:06
【问题描述】:

如果我将 VS 设置为在给定类型的抛出异常时中断,并且调试器在某段代码处停止,我会寻找继续运行 (F5) 并且 中断每个代码的可能性相同异常的父堆栈帧。

换句话说,我希望有可能忽略堆栈帧其余部分的异常实例(假设它在上面的某个地方被捕获)。

我发现的唯一方法是乏味的(如果在某些情况下经常抛出此类异常,则容易出错):取消选中“抛出此类型时中断”复选框,继续执行,立即在“异常设置”窗格中重新激活异常.


编辑:澄清第一个答案

我忘了提到(因为我不知道这是相关信息)我在异步方法中。我将您的示例修改为异步,如下所示:

    public static class Program
{
    public static void Main(string[] args)
    {
        try
        {
            Alpha();

        }
        catch (Exception e) // don't try this at home kids
        {
            // we should never get here in this example
            throw;
        }
    }


    private static async Task Alpha()
    {
        try
        {
            await Bravo(); //  *** 4 ***
        }
        catch (Exception e)
        {
            // debugger won't stop here because we didn't re-throw
        }
    }

    private static async Task Bravo()
    {
        try
        {
            await Tango(); //  *** 2 ***
        }
        catch (Exception)  // don't try this at home kids
        {
            throw;  // *** 3 *** debugger will stop here again because we are re-throwing
        }
    }

    private static async Task Tango()
    {
        var x = 1;
        var y = 0;
        var c = x / y; //  *** 1 ***

    }
}

并且调试器在编号顺序的所有四个标记点处停止。所以它不仅在重新抛出时停止,而且在两者之间完全等待。对于深层调用层次结构,可以这么说,这会扰乱我的调试流程。

总而言之,我需要一种异步调用解决方案,以便在导致异常的堆栈帧和最终捕获异常的堆栈帧之间的每次等待都不会重新中断。

可能吗?

【问题讨论】:

  • async 代码不正确。因为您没有await Alpha(),所以程序在其余代码完成之前终止。在我的机器上,程序在Tango() 甚至尝试除以零之前终止,更不用说抛出异常了。此外,您甚至没有创建任何Tasks
  • 哎呀,最后忽略了,我现在正在使用我的家用电脑,并且没有打开异常抛出的中断。给我一点时间。
  • 是的,不等待 Alpha() 在实际应用程序代码中会出现问题,在此示例中,它与我们正在讨论的问题无关,因此请忽略它;)抛出,问题在示例中变得很明显。
  • 顺便说一句,msdn 文档说:“如果您等待导致异常的任务返回异步方法,则等待运算符会重新引发异常。” (见msdn.microsoft.com/en-us/library/hh156528.aspx)。所以基本上我是在问“如何忽略突破时的重新投掷”。 :-/
  • 我稍微修改了标题并添加了一个新的tag,希望其中一位异步大师可以提供帮助:)

标签: c# visual-studio exception async-await


【解决方案1】:

随着问题中出现的新信息,这个答案可能不再合适。 :)


如果我将 VS 设置为在给定类型的抛出异常时中断,并且调试器在某些代码处停止,我会寻找继续运行 (F5) 的可能性,而不是在同一异常的每个父堆栈帧上中断....

我发现的唯一方法是乏味的(如果在某些情况下经常抛出此类异常,则容易出错):取消选中“抛出此类型时中断”复选框,继续执行,立即在“异常设置”窗格中重新激活异常

没有看到您的代码,我只能假设您重新抛出相同的异常。

考虑以下代码:

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Alpha();

        }
        catch (Exception e) // don't try this at home kids
        {
            // we should never get here in this example
            throw;
        }

    }

    private static void Alpha()
    {
        try
        {
            Bravo();
        }
        catch (Exception e)
        {
            // debugger won't stop here because we didn't re-throw
        }
    }

    private static void Bravo()
    {
        try
        {
            Tango();
        }
        catch (Exception)  // don't try this at home kids
        {
            throw;  // debugger will stop here again because we are re-throwing
        }
    }

    private static void Tango()
    {
        var x = 1;
        var y = 0;
        var c = x / y;
    }
}

System.DivideByZeroException 被抛出时调试器设置为中断,调试器将:

  1. 首先在Tango 停止,尝试除以零并引发第一个异常
  2. 在再次引发异常的Bravo 中的catch() 处理程序中再次停止

但它不会停在Alpha,因为我默默地吃异常。

您看到的行为是设计使然。

【讨论】:

  • 啊,是的,但请看我上面的编辑。这不适用于异步方法。
  • 为更多信息干杯。是的,可悲的是,我认为我的回答现在没有多大用处。正如您在文档中指出的那样,等待和抛出异常时的行为非常有趣。 :)
  • 本文档分享了有关为什么在异步中未拦截异常的有用信息:blogs.msdn.microsoft.com/ptorr/2014/12/10/async-exceptions-in-c
  • 感谢链接(已添加书签),但在此问题中,我正在考虑捕获的异常(不是未处理的异常)。
  • @JackZhai-MSFT 谢谢,但我们不是在谈论这个
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-12
  • 1970-01-01
  • 2010-11-23
  • 2022-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多