本文假设读者了解VS的基本调试知识,如:F5开始使用调试器运行程序F9在当前行设置断点F10到运行到下一个断点F5从停止的正在调试的程序恢复执行F11进入一个函数(如果当前程序指针指向一个函数)F10跳过一个函数(如果当前程序指针指向一个函数)Shift+F11步进从执行的函数中暂停执行附加到鼠标悬停时快速查看进程源代码中的元素调试窗口:局部变量、监视、即时窗口、模块、调用堆栈、异常设置许多开发人员使用这个强大的工具包来调试会话。但是,VisualStudio调试工具提供了更多的功能。下面是一组VisualStudio调试效率提示。注意这些提示和快捷方式已经在Visualstudio201916.6EN-US版本中验证过了,验证时Visualstudio没有安装扩展。1、运行到光标所在位置使用快捷键Ctrl+F10,使调试器运行到光标所在行。2、点击鼠标运行到当前位置。在调试正在运行的程序时,将鼠标悬停在当前代码行上时,会出现一个绿色符号。可以点击这个符号直接让断点运行到这里。3.将此作为下一条要执行的语句。调试正在运行的程序时,按住Ctrl键将鼠标悬停在当前代码行上,将其转换为下一条要执行的语句。不同于通过绿色箭头符号跑到这里,这个函数会跳过中间的语句,直接跳到这里的断点。因此,在下面的动画中,我们可以看到watchwindow中引用的obj还是null,中间的MyClass构造函数还没有执行。4.数据断点:当值改变时,触发断点(breakwhenthevaluechanges)。将非静态setter设置为断点时,当所有对象属性的值发生变化时触发断点。通过本地窗口(监视窗口)右键单击:在值更改菜单上中断,也可以为单个对象获得相同的行为。下面的动画演示了这个功能,只有当obj2.Prop改变时才会触发断点,而当obj1.Prop改变时不会触发断点。注意:数据断点旨在在绑定??到活动对象时在调试期间工作。因此,调试过程一旦停止,设置的断点就丢失了,无法在后续的调试过程中再次使用。5.条件断点条件可以附加到断点上,只在特定场景下触发中断。在下面的动画中,我们在循环中定义了一个条件为i>6的断点。然后点击Continue,可以看到一旦断点停止,i的值实际上变成了7。6.跟踪断点是遇到断点停止程序执行时最常见的操作。但是,您可以选择在输出窗口中不终止(或终止)打印一些跟踪信息。下面的动画说明了这种可能性。我们在输出窗口中跟踪i从0到9的值。注意:跟踪断点在编辑器的断点显示位置显示为菱形。请注意,可以在断点上指定条件和跟踪操作。7.超出范围的跟踪对象在监视窗口中,通过当前执行模板中引用的名称跟踪对象。然而,当这样的跟踪引用超出范围时,即使引用对象仍然存在,它在监视窗口的上下文中也是无意义和禁用的。在许多情况下,我们希望跟踪范围外对象的状态。为此,在观察窗口中右键单击此类引用,单击菜单[MakeObjectID]创建一个对象ID(M),并添加$1(或$2、$3、...,具体取决于您已创建多个对象ID)。下面的gif演示了如何跟踪范围外对象的属性获取器的状态,该获取器将实际日期时间作为字符串返回。它很好地表明,当对obj的引用超出Fct()上下文中的范围时,要监视的obj项将被禁用,而$1仍会更新。8、查看函数返回值函数返回值在源代码中有时会被忽略,或者有时在调试时无法显式访问到这个值。这样的返回值可以显示在Debug->Window->Auto窗口中。伪变量$ReturnValue也可以用在立即窗口和观察窗口中,方便查看上次函数调用的返回值。请注意,只有当VisualStudio调试器附加到进程并且程序被调试器暂停时,菜单调试->窗口->自动窗口才可用。9.ReattachtoProcess从VisualStudio2017开始,提出了ReattachtoProcess工具Shift+Alt+P,非常方便。将调试器附加到进程后,VisualStudio会记住它并建议将调试器重新附加到同一进程。相同的斜体,因为这里有一个关于进程ID的试探法:如果附加的进程仍在运行,则重新附加到该进程,重新附加到它。否则,VisualStudio将尝试查找与先前进程名称同名的单个进程,并将调试器重新附加到该进程。如果找到多个具有此名称的进程,“附加到进程”对话框打开,并且仅显示具有相同名称的进程如果没有找到具有此名称的进程,则显示“附加到进程”对话框适用于调试涉及多个会话过程。在这种情况下,VisualStudio会尝试使用上述相同的试探法查找它附加到的所有进程。10.立即窗口和监视窗口中的无副作用计算有时,在立即窗口或监视窗口中计算表达式时,某些状态会发生变化。这种行为通常是不可取的。您不想仅仅因为需要计算表达式的值就破坏调试器的状态。这种情况被称为Heisenbug,这是对物理学家WernerHeisenberg的双关语,他首先断言了量子力学的观察者效应,即观察系统的行为不可避免地会改变其状态。为避免更改任何状态,您可以在表达式后添加nse(No-Side-Effect)。下面的动画说明了这种可能性(在观察窗口中观察状态值的变化)。下面的动图是监控窗口中nse的使用。由于SideEffectFct()观察的项目中的刷新评估按钮,此示例比上一个示例更简单。11.在源代码中显示线程调试多线程应用程序是出了名的复杂。希望在源代码中显示线程按钮会有很大帮助。它在编辑器的左侧栏中引入了标记图标,以跟踪其他线程暂停的位置。此标志可用于显示线程ID,并最终切换到另一个线程。注意:如果至少有两个线程在同一位置暂停,则会显示不同的标记符号。有关调试多线程应用程序的更多提示,请参见此Microsoft文档:开始调试多线程应用程序(C#、VisualBasic、C++)https://docs.microsoft.com/en-us/visualstudio/debugger/get-started-debugging-multithreaded-apps?view=vs-2019下面是本次演示的源码。如果要演示,可以参考:usingSystem;usingSystem.Threading;classProgram{staticvoidMain(){for(inti=0;i<5;i++){//Avoidcapturingaloopvariableinthelambdabelowintj=i;//所以2threadareblockedon'0'caseif(j==1){j=0;}ThreadPool.QueueUserWorkItem(delegate{Method(j);});}Thread.Sleep(60000);}staticvoidMethod(intid){switch(id){case0:Thread.Sleep(60000);break;case1:Thread.Sleep(60000);break;case2:Thread.Sleep(60000);break;case3:Thread.Sleep(60000);break;case4:Thread.Sleep(60000);break;}}}12.从反编译的IL代码调试源代码我们经常依赖一些黑盒组件:我们没有源代码的组件。但是,在调试复杂行为时,观察甚至调试被引用的黑盒组件所引用的逻辑。这就是为什么从16.5版开始,VisualStudio2019可以从已编译的程序中生成一些源代码。这样的源代码是可调试的。此功能基于开源软件(OSS)项目:ILSpy(https://github.com/icsharpcode/ILSpy)。反编译菜单可以在模块窗口的组件右键菜单中给出(如下动画所示),也可以在SourceNotFound或NoSymbolsLoaded对话框中给出。将IL代码反编译为源代码不可能是完美的,因为在编译时会丢失一些源代码信息。因此,此功能有一些限制,在本官方文档末尾进行了解释:Generatesourcecodefrom.NETassemblieswhiledebugginghttps://docs.microsoft.com/en-us/visualstudio/debugger/decompilation?view=vs-2019
