Reputation: 7215
Something that has bugged me for a long time I've finally decided to ask here on stackoverflow:
Why is it that while executing a Windows Forms project in DEBUG mode that when I click the pause button that it will always stop on Application.Run?
Application.Run(new FormGuiV2()); // pressing pause stops here
This seems like a flaw to me. Why doesn't it pause on the actual line of code being executed? Stopping at the top of the stack is not helpful when debugging. I think I must be using the debugger incorrectly?
To get around it I have to be aware of what lines of code are being executed and place a debug point, which is error prone and sometimes time consuming to track down where I want to place the debug point.
I'd like to know the proper way to click the pause button and have it actually stop at the executing line of code.
Thanks
Upvotes: 2
Views: 765
Reputation: 942428
It doesn't, it stops at whatever code was active while you gave the Debug + Break command. Which you can see in the debugger's Call Stack window. The odds that you'll interrupt any of your own executing code are however quite small, your program spends 99% of the time waiting for Windows to tell it that something interesting happened. Which makes the call stack typically look like:
[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]
Note how the FPushMessageLoop() method is on top of the stack trace. That's the famous message loop in a Windows GUI app, the one that receives Windows notifications. If you also enable unmanaged debugging then you'll see more, the core GetMessage() winapi function is an essential part of the message loop.
Do note the >
marker in the stack trace. That's the line of code you are talking about. The reason you see it is because the code above it is part of the .NET framework. And you don't have source code for it if you didn't install the Reference Source.
So the debugger just walks the stack down, looking for any relevant source code to display. And inevitably will end up in your Main() method inside Program.cs, the Application.Run() call.
Getting useful breaks in a GUI app requires setting breakpoints.
Upvotes: 6
Reputation: 244981
That more than likely is the actual line of code being executed.
Well, actually, code inside of the Application.Run
method is being executed, but that code is part of the .NET Framework libraries and you don't have .NET source stepping turned on. If you did, it would dump you somewhere inside of the labyrinth of WinForms library code, which you probably wouldn't find very helpful either.
The secret behind this mystery is that Windows application spend most of their time waiting in a loop, waiting for messages from the operating system based on user input and other events. This is called the message loop. The .NET Framework (and other frameworks) abstract this all away for you, processing these messages internally and exposing the important stuff to you in other ways (e.g. by raising events). But it's all still going on behind the scenes.
You have to time it just right in order to randomly hit the "pause" button and break somewhere into user code. Most of the time when you break execution, the code is at an "idle" point, waiting for user input or some other action. Therefore, breakpoints are usually a better, more manageable approach.
Upvotes: 2
Reputation: 115037
The Main thread, the one that launched the application, will be at Application.Run
, otherwise the application would have closed. The Application.Run
spins up the UI Thread and possibly others which is where your expected position is.
The Main Thread of the application is where the debugger will always jump to. That's the one thread that should always be there, since the process would close otherwise.
When you open the Debug->Windows->Threads window you can switch to the other threads, you will see that one of them is actually paused on the location you're probably expecting it.
See: http://msdn.microsoft.com/en-us/library/w15yf86f.aspx
Upvotes: 2