TL; DR - 是否有'递归'[DebuggerStepThrough]
?
我是否可以在方法上使用某个属性,以便在使用 Debug>时在一个空闲的WinForms表单上打破所有,然后单步执行Application.Run()
,这样当一个事件调用该方法时,该方法或它调用的任何东西都不会触发断点?
以下是一些简单的示例代码,用于说明问题¹:
static void Main() {
Application.Run(new MyForm()); //I step (F11) into here to wait for events of interest
}
string GetSome {
get { //I don't want to wind up on a breakpoint here
return "Some"; //as a result of OnActivated() being called!
} //But I *DO* want to be able to step in here otherwise,
} //(e.g. as a result of OnClick() being called.²
[DebuggerStepThrough] //Not interested in this event or anything it calls
protected override void OnActivated(EventArgs e){
string come = GetSome;
}
protected override void OnClick(EventArgs e){ //But I *AM* interested in this event
string come = GetSome;
}
我在做什么:一旦我的WinForms表单完全初始化,得到了焦点,现在处于空闲状态(消息循环中没有排队的消息)(标记1) ,我用 Debug>暂停空闲表单全部打破。表单处于空闲循环中,因此调试器将最顶层的堆栈帧显示为 [外部代码] ,前一个堆栈帧为Application.Run()
行。然后我点击了F11(Step Into)。表单的消息循环恢复,表单重新激活并获得焦点。 (标记2)一旦托管框架出现在堆栈顶部,调试器现在就会暂停 - 例如一旦上述代码中的一个事件发生。 (标记3)重新激活表单会导致OnActivated()
被调用。
所需行为
我希望调试器忽略OnActivated()
以及它可能调用的任何其他内容。单击恢复的表单后,我希望调试器在OnClick()
上暂停,因为调试器正在等待托管帧到达堆栈顶部。
实际发生的事情:
调试器忽略OnActivated()
(因为它标记为[DebuggerStepThrough]
) - 好,但暂停在GetSome
getter - bad 中。此时:
GetSome
getter,表单会再次重新激活,然后我回到标记2 并且我处于循环中。 有趣的是,调试器实际上忽略了“调试>选项>调试>常规>在标记3 上跳过属性和运算符”选项。如果我在启动表单时手动进入(F11)GetSome
,启用“跳过属性和运算符”,调试器不会暂停{来自Application.Run()
的{1}} getter!
¹代码中的任何地方都没有设置明确的断点。在我正在处理的实际代码中,我试图让调试器忽略一些特定的重绘事件(以及他们从其他类调用的任何方法和访问器),同时能够使用“Break All + F11”作为步入任何下一个事件的快捷方式(有许多可能性),而不必在每个事件上设置明确的断点。
²我不能仅仅标记“无趣”事件使用GetSome
属性调用的所有其他方法的原因有两个:我所谓的几个“无趣”事件我已经调用了数百个其他方法 - 这是很多重构和可见的杂乱添加;当然,当我真正需要调试时,我将失去逐步完成这些方法的能力。