长期困扰我的东西我终于决定在stackoverflow问这里:
为什么在DEBUG模式下执行Windows窗体项目时,单击暂停按钮时它将始终停在 Application.Run 上?
Application.Run(new FormGuiV2()); // pressing pause stops here
这对我来说似乎是一个缺陷。为什么它不会暂停在正在执行的代码行上?调试时,在堆栈顶部停止是没有用的。我想我必须错误地使用调试器?
为了解决这个问题,我必须知道正在执行哪些代码行并放置一个调试点,这很容易出错并且有时很耗费时间来追踪我想放置调试点的位置。
我想知道点击暂停按钮的正确方法,并让它实际停在执行的代码行。
由于
答案 0 :(得分:6)
它没有,它在您给出Debug + Break命令时停止在任何活动的代码处。您可以在调试器的“调用堆栈”窗口中看到该内容。然而,你中断任何你自己的执行代码的可能性非常小,你的程序花99%的时间等待Windows告诉它发生了一些有趣的事情。这使得调用堆栈通常如下所示:
[Managed to Native Transition]
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(System.IntPtr dwComponentID, int reason, int pvLoopData) + 0x444 bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason, System.Windows.Forms.ApplicationContext context) + 0x155 bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x4a bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form mainForm) + 0x31 bytes
> WindowsFormsApplication1.exe!WindowsFormsApplication1.Program.Main() Line 16 + 0x1d bytes C#
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x6b bytes
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x27 bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x6f bytes
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0xa7 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x16 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x41 bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes
[Native to Managed Transition]
注意FPushMessageLoop()方法如何位于堆栈跟踪之上。这是Windows GUI应用程序中着名的消息循环,即接收Windows通知的应用程序。如果您还启用了非托管调试,那么您将看到更多内容,核心GetMessage()winapi函数是消息循环的重要组成部分。
请注意堆栈跟踪中的>
标记。这就是你所谈论的代码行。你看到它的原因是因为它上面的代码是.NET框架的一部分。如果您没有安装参考源,那么您就没有源代码。
因此,调试器只需向下移动堆栈,查找要显示的任何相关源代码。并且不可避免地会在Program.cs中的Main()方法中结束,即Application.Run()调用。
在GUI应用程序中获取有用的休息时间需要设置断点。
答案 1 :(得分:2)
启动应用程序的主线程将位于Application.Run
,否则应用程序将关闭。 Application.Run
旋转UI线程,可能还有其他位置,这是您预期的位置。
应用程序的主线程是调试器总是跳转到的位置。这是应该始终存在的一个线程,因为否则该过程将关闭。
当您打开Debug-> Windows->线程窗口时,您可以切换到其他线程,您将看到其中一个线程实际上暂停在您可能期望的位置。
答案 2 :(得分:2)
很可能 正在执行的实际代码行。
实际上,正在执行Application.Run
方法的内的代码,但该代码是.NET Framework库的一部分,并且您没有转换.NET源代码上。如果你这样做了,它会把你转移到WinForms库代码迷宫中的某个地方,你可能也找不到它。
这个谜团背后的秘密是Windows应用程序将大部分时间等待循环,等待来自操作系统的消息基于用户输入和其他事件。这称为message loop。 .NET Framework(以及其他框架)为您提取所有内容,在内部处理这些消息并以其他方式向您展示重要内容(例如,通过引发事件)。但它仍然在幕后进行。
你必须及时计时才能随机点击“暂停”按钮并在某处进入用户代码。大多数情况下,当您中断执行时,代码处于“空闲”点,等待用户输入或其他操作。因此,断点通常是更好,更易于管理的方法。