2011-01-11 40 views
1

我有一個C#.NET多線程應用程序凍結了界面。不尋常的是,除非我讓系統閒置足夠長的時間以使屏幕保護程序啓動(這要求我重新輸入密碼以重新訪問系統),否則界面不會凍結。當界面再次可見時(在我成功輸入密碼後),界面被鎖定。只要我不讓屏幕保護程序啓動,那麼界面不會鎖定。多線程c#應用程序中的界面凍結

我應該指出,我有兩個不同的可執行文件訪問相同的DLL,並且無論使用哪個應用程序訪問該DLL,都會發生此問題。這似乎意味着問題出在DLL上,因爲除了它們與DLL的關聯外,這兩個應用程序完全不同(C++/MFC)和(C#/ .NET)。

這兩個exes在它們如何與DLL交互時執行類似的步驟。他們調用dll來設置串口通信,在DLL中打開一個狀態窗口,在DLL中啓動一個線程來監視通信端口,然後在主應用程序中啓動一個監視dll中棧的線程。

當通過DLL中的線程從通信端口獲取數據時,將對其進行分析,並將其結果放置在堆棧上,然後通過委託將其發佈到狀態窗口。當exe中的線程看到堆棧中的數據時,它會使用委託在主窗口中輸出數據。

我發現,如果我將代碼添加到DLL中的線程,因此它每30秒調用一次Application.DoEvents(),界面將被凍結約30秒,然後像平常一樣恢復活動。 我認爲某些東西阻塞了主線程並強制DoEvents()發射似乎破壞了鎖定,但我不知道可能會導致此鎖定。

在我的開發機器和測試機器上都會出現此問題。

我已經嘗試完全刪除數據的輸出到DLL中的狀態窗口,但沒有任何區別。

我一直在做多線程編程多年,從未見過這樣的事情;所以任何意見將不勝感激。

謝謝。

+3

暫停調試器中凍結的用戶界面並查看調用堆棧。 – SLaks 2011-01-11 15:35:25

+0

您是否嘗試過僅從非UI線程調用DLL方法並編組到UI線程? – RobS 2011-01-11 15:36:35

回答

6

這是一個通常由SystemEvents類引發的問題,當您使用非標準方式初始化用戶界面時。特別使用線程。啓動你的程序,Debug + Break All,Debug + Windows + Threads。如果你看到一個名爲「.NET SystemEvents」的線程,那麼你幾乎肯定會得到這個掛起。

一些背景:SystemEvent類支持控制檯模式應用程序和GUI應用程序。對於後者,它應該在UI線程上觸發它的事件處理程序。第一次訂閱其中一個事件時,會創建一個隱藏的幫助窗口以獲取系統通知。它可以通過兩種方式來完成,無論是通過在調用線程上創建窗口還是通過啓動輔助線程來完成。它根據Thread.GetApartmentState()的值作出決定。如果是STA,那麼它可以在調用線程上創建窗口,並且可以將所有事件回調正確地編組到該線程。

如果您創建的第一個窗口未在UI線程上創建,則會出錯。例如,一個啓動畫面。該窗口可能包含對像UserPreferenceChanged這樣的系統事件感興趣的控件,以便它們可以正確重繪自己。它現在使用助手線程,並且將從該助手線程中觸發任何事件,而不是UI線程。毒害任何在UI線程上運行的窗口。會話切換出鎖定的工作站(包括屏幕保護程序)是出於某種可能導致死鎖的神祕原因。您也可能會偶爾看到偶然的繪畫事故,即使用來自錯誤線索的Windows的不太討厭的結果。

從固定的初始化命令短,一個解決方法是把這個在您的Main()方法,創建之前的任何窗口:

Microsoft.Win32.SystemEvents.UserPreferenceChanged += delegate { }; 
0

的問題確實出現了相關的ActiveX控件可能是在形式上使用不正確。我切換到在.NET中使用串行端口庫,並沒有能夠重現我的問題。感謝大家,尤其是漢斯的幫助。

0

我遇到了同樣的問題,因爲當屏幕保護程序啓動或我鎖定我的電腦和顯示器進入睡眠狀態時,我的電腦會掛斷。 我95%確定在我的多線程應用程序中出現死鎖。查看並確定代碼中是否存在任何死鎖。