DebuggerStepperBoundaryAttribute的一个使用示例是什么?

16
我熟悉 DebuggerHiddenAttributeDebuggerStepThroughAttribute。今天我注意到了 DebuggerStepperBoundaryAttribute,如果我理解正确的话,如果你试图在带有该属性的属性(或方法或其他内容)上按 F10 键,它会变成 F5。

使用 DebuggerStepperBoundaryAttribute 从代码步进转换为运行代码。例如,在使用 F10 键(或“逐过程”命令)步进代码时遇到 DebuggerStepperBoundaryAttribute,与按下 F5 键或使用“开始调试”命令具有相同的效果。

我想不出这将是有用/有帮助的例子。所以要么我的理解是错误的,要么我想不出它如何有用。有哪些使用 DebuggerStepperBoundaryAttribute 的例子是有用/有帮助的?

我可以想象,如果你有一个任务计划程序或类似的东西,并且已经完成了任务,它可能会很有用。而不是回到框架代码中,它只会让任务完成并消失在后台。但就个人而言,我没有使用过它。 - jessehouwing
对于正在调试的开发人员来说,这似乎非常令人困惑。 - usr
@usr 我就是这么想的。 - Daryl
1
在.NET 4.5源代码中,只有2个类和4个方法实际上使用了这个属性。其中一个确实记录了其使用原因,但我找不到任何引用文献。我对这个属性进行的所有测试都产生了毫无价值的结果,而我认为它可能是有用的。http://referencesource.microsoft.com/#mscorlib/system/diagnostics/debuggerattributes.cs,7242c2844bdaf319,references - TyCobb
@TyCobb - 看起来这两件事都在创建新的线程。我想知道它是否是用于此...如果你正在创建一个新线程,则不要允许“步入”进入一个新线程? - Daryl
2个回答

3
[DebuggerStepperBoundary] 字面意思是调试边界。通常情况下,调试器会跳过这个边界(无论你有多喜欢StepInto),但是它确实允许您设置断点,在这种情况下,它会停在那里。但通常的行为是跳过此函数(运行)。
[DebuggerStepThrough] 这意味着您永远无法在这里中断。如果尝试设置断点,则只要选择了“仅我的代码”,该断点将显示为禁用状态。通常用于属性、linq等。
何时使用这个:
我有一个应用程序,使用user32.dll向特定应用程序发送按键。我在90%的这些功能上放置了DebuggerStepThrough,因为它们没有被中断是没有影响的。它们需要作为整体运行。
希望这回答了您的问题。

我假设你的意思是“BUT IT”而不是“IN”。 那么,StepThrough和StepperBoundary之间唯一的区别是什么?除非选择了“仅我的代码”,否则无法在StepThrough中设置断点吗? - Daryl
是的,它的兄弟[DebuggerNonUserCode]被生成的代码使用,而StepThrough是非生成代码的直接兄弟。 - Mickey Perlstein
调试器单步执行是我用于那些我知道其他开发人员会遇到的事情,比如我的sendkeys示例或简单属性,以及当我不想在调试时看到它时的边界。 - Mickey Perlstein
值得注意的是,在Jetbrains Rider中,DebuggerNonUserCodeDebuggerHidden没有任何效果。 - Steve Dunn
@SteveDunn 我认为这些是针对 .NET Core 之前的版本。 - Mickey Perlstein

2
以下是一个简单的测试程序(启用“仅限我的代码”,并在测试1、2、3和4行上设置断点),如下所述:
class Program
{
    static void Main(string[] args)
    {
        TestDebuggerStepperBoundary();                        // Test 1
        Test();                                               // Test 2
        TestDebuggerNonUserCode(TestDebuggerStepperBoundary); // Test 3
        TestDebuggerNonUserCode(Test);                        // Test 4
    }

    [DebuggerNonUserCode]
    private static void TestDebuggerNonUserCode(Action action) { action(); }

    [DebuggerStepperBoundary]
    private static void TestDebuggerStepperBoundary() { SomethingHorrible(); }

    [DebuggerNonUserCode]
    private static void Test() { SomethingHorrible(); }

    private static void SomethingHorrible()
    {
        var foo = "bar";
    }
}

检查DebuggerStepperBoundaryAttribute的定义之后,我认为这个定义不太正确:

DebuggerStepperBoundaryAttribute属性用作从DebuggerNonUserCodeAttribute的影响中逃脱的方法。

您可以在不处于DebuggerNonUserCodeAttribute上下文的情况下使用DebuggerStepperBoundaryAttribute。 在测试1上按F11会立即命中测试2上的下一个断点,而不处于“DebuggerNonUserCodeAttribute的影响下”。 我认为这应该真正读作“DebuggerStepperBoundaryAttribute属性用作在调试时跳过Step Into或Step Over的方法。” 其余的定义是有道理的:
在DebuggerNonUserCodeAttribute的边界内执行时,由设计者提供的代码将作为一步一步执行,直到遇到下一个用户提供的代码。当在线程上进行上下文切换时,进入的下一个用户提供的代码模块可能与正在调试的代码无关。为了避免这种调试体验,请使用DebuggerStepperBoundaryAttribute来从步进代码转换为运行代码。例如,在Visual Studio 2005中,使用F10键(或Step Over命令)步进代码时遇到DebuggerStepperBoundaryAttribute具有与按下F5键或使用Start Debugging命令相同的效果。
因此,回答我的问题,如果有其他代码需要调用,但您无法/不愿添加DebuggerStepThrough、DebuggerNonUserCode或DebuggerHidden,但是如果调试器进入方法会比从调试代码到运行代码更令人震惊,那么请使用DebuggerStepperBoundaryAttribute。(在我的示例程序中,对Test 2按F11键,直接跳转到SomethingHorrible可能比直接运行(F5)更糟糕。)它显式地添加了线程上下文切换,并且除此之外,我不知道还有哪种情况会有用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接