2013-07-12 26 views
1

一些長期困擾我的東西我終於決定在這裏問個問題stackoverflow:視覺工作室IDE按暫停按鈕停在運行不是我想要的地方?

爲什麼在DEBUG模式下執行Windows Forms項目時,當我點擊暫停按鈕時,它總是會停止在Application.Run

Application.Run(new FormGuiV2()); // pressing pause stops here 

這似乎是一個缺陷給我。爲什麼它在正在執行的實際代碼行上暫停?調試時停止在堆棧頂部是沒有幫助的。我想我必須錯誤地使用調試器?

爲了解決這個問題,我必須知道哪些代碼行正在執行,並且放置一個調試點,這很容易出錯,並且有時需要耗費時間來追蹤我想要放置調試點的位置。

我想知道正確的方法來點擊暫停按鈕,並讓它停在執行代碼行。

感謝

回答

6

它沒有,它停止在你給出Debug + Break命令時任何代碼處於活動狀態。你可以在調試器的Call Stack窗口中看到。然而,你會打斷你自己執行代碼的機率很小,你的程序花費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應用程序中獲得有用的中斷需要設置斷點。

+0

這是不幸的。另一個原因是我更喜歡從單元測試中進行調試。從單元測試中,我確信暫停按鈕會停在我寫的代碼上 - 而不是着名的循環。 – sapbucket

+1

呃,不,這當然不能保證。它也可能在代碼被深埋在winapi或框架調用中時破壞。唯一的區別是,您可能認爲調試器選擇的源代碼文件與您更相關。這實際上只是這種情況,因爲單元測試不會在99%的時間內無所事事。所以,也許真正的問題是,使用Debug + Break All時,由於代碼並未執行,因此在使用它時沒有意義。當代碼陷入循環時,你只會真的需要它。 –

2

主線程,即啓動的應用程序之一,將在Application.Run,否則該應用程序會關閉。 Application.Run旋轉UI線程和其他可能是你期望的位置的地方。

應用程序的主線程是調試器總是跳轉到的地方。這是一個應該始終存在的線程,因爲過程會關閉,否則。

當您打開Debug-> Windows-> Threads窗口時,您可以切換到其他線程,您將看到其中一個實際上已暫停在您可能期望的位置。

參見:http://msdn.microsoft.com/en-us/library/w15yf86f.aspx

2

這被執行更有可能的實際代碼行。

嗯,事實上,代碼Application.Run方法正在執行,但該代碼是.NET Framework庫的一部分,你沒有.NET源步進開啓。如果你這樣做了,它會將你轉儲到WinForms庫代碼的迷宮中,你可能也找不到任何有用的東西。

這個祕密背後的祕密是Windows應用程序花費大部分時間在等待在一個循環中,等待來自操作系統的消息根據用戶輸入和其他事件。這被稱爲message loop。 .NET Framework(和其他框架)將這些內容全部抽象出來,在內部處理這些消息,並以其他方式向您展示重要內容(例如,通過提升事件)。但這一切仍在幕後進行。

您必須時間恰到好處,才能隨機點擊「暫停」按鈕並切入用戶代碼。大多數情況下,當您執行時,代碼處於「空閒」狀態,等待用戶輸入或執行其他操作。因此,斷點通常是更好,更易於管理的方法。