2010-11-02 47 views
9

我一直在困擾着可怕的OnUserPreferenceChanged杭多數民衆贊成refered到相當不錯的伊萬Krivyakov,在這裏:.NET 4.0和可怕的OnUserPreferenceChanged杭

http://ikriv.com/en/prog/info/dotnet/MysteriousHang.html#BeginInvokeDance

我張貼的問題而回,當我最初碰到的問題:

Yet another C# Deadlock Debugging Question

我以爲我已經通過刪除構建關閉UI線程控制解決它,但是一點點得到控制而之後它再次出現(可能永遠不會離開...)。

我們一直在使用.NET 3.5,我知道它使用CLR 2.0。最近,應用程序已升級爲使用.NET 4.0 Client Profile/CLR 4.0。另外,我們已經從Infragistics WinForms 10.1升級到10.3。唯一的區別是以前的版本被混淆了......有沒有人遇到過混淆和懸掛的問題?我已經有另一個刺激擺脫任何應用程序一勞永逸的掛起,但不尋常的是,我沒有能夠在最新版本(使用.NET 4.0)重現掛起。使用Ivan Krivyakov的方便的Freezer應用程序(請參閱他的文章)可以很容易地在以前的版本(使用.NET 3.5)中進行復制,該應用程序根據請求觸發WM_SETTINGCHANGE消息。

這可能是我有點希望這個問題已經自行消失了,但有誰知道是否有任何更改CLR從2.0到4.0會導致此?

--------------------------------------------- - - - - 解 - - - - - - - - - - - - - - - - - - - - - ---------

因此,在測試應用程序的變化後,例如CLR 2.0 + Infragistics 2010.1,CLR 2.0 + Infragistics 2010.3和CLR 4.0 + Infragistics 2010.1,我們相信我們發現這個問題已經成爲WinForms 2010.1中Infragistics組件的一個問題(沒有熱修復)。我們還沒有使用CLR 2.0或CLR 4.0與Infragistics 2010.3重現凍結,相反(現在我們已經很好地重現了這一點......)。

+0

I. Krivyakov的新鏈接文章:[Mysterious Hang](http://www.ikriv.com/dev/dotnet/MysteriousHang.html) – tibx 2017-04-07 09:57:42

回答

15

是構建關閉UI線程控制...

是的,這是引發這一問題的好辦法。根本的問題是由SystemEvents類引起的,它具有在正確的線程上引發事件的不可饒恕的任務。 UserPreferenceChanged事件是典型的麻煩製造者,許多控件都訂閱它,以便在用戶更改桌面主題時重新繪製自己。組件供應商不會忽視這一需求。工具箱中的標準.NET框架控件也沒有。

測試此問題的一種比較好的方法是鎖定工作站(按Win + L鍵),以及在用戶機器上常常觸發死鎖的方式。切換到安全桌面往往會觸發事件。由於額外的怪癖,當你調試你的程序時,這種情況永遠不會發生,並且它具有棘手的與時間有關的行爲,因爲這往往會發生在沒有人在機器上時。特別難調試。

這種陷入麻煩的一種標準方式是由於程序中的初始化問題。訂閱的第一個SystemEvents事件會導致SystemEvents類自行初始化,並設置接收這些通知並引發相應事件所需的管道。一個自定義的啓動畫面太多(即不僅僅是顯示一個位圖)並且在標記爲STA的工作者線程上運行足以導致此錯誤。像ProgressBar一樣簡單就足夠了。 SystemEvents假定工作線程是程序的主線程,現在可以輕鬆地在未來的錯誤線程上生成事件。對此有一個很好的診斷,如果那個工作線程不在那裏,那麼就會產生第一次機會異常。你可以在Output窗口看到它。

或者您創建另一個UI線程並在兩個線程上都有表單。不可避免地,其中一種形式總是會在錯誤的線索中引發事件。

唯一合適的建議是承認在工作線程上創建UI是微軟不知道如何正確執行的火箭科學。值得注意的是,.NET 1.x控件具有一個事件處理程序,當它從錯誤的線程調用時它仍能正常工作,它只是調用Control.Invalidate()。但那是知識,似乎已經在2.0丟失,ToolStrip是good example。並且不要相信組件供應商能夠做到這一點,Infragistics尤其不具備良好的聲譽。不要這樣做。

+0

感謝您提供令人耳目一新的信息,Hans!我們確實有一個通過對Application.Run()的獨立調用創建的Splash屏幕,我不滿意它會給它自己的消息泵......只要我們將任何調用放入splash,它就會安全。這是不正確的嗎?我不知道有一些內置的.NET支持閃屏。我會看看。 – Roo 2010-11-02 16:53:21

+0

另外,你是否知道爲什麼我無法使用使用CLR 4.0的應用程序的未混淆版本來重現此掛起? – Roo 2010-11-02 16:55:27

+0

死鎖對定時非常敏感。發佈版本中的時序與調試版本不同。這聽起來並不像你對處理這個問題的方式有很大的幫助。我建議我提出的解決方法。 – 2010-11-02 17:06:07

1

我已經找到了解決這個問題的最好的指南是在這裏:

它會引導你使用的WinDbg驗證錯誤的原因,並告訴您如何找到是什麼造成的。正如你所提到的,它最有可能是由於在非UI線程上創建了一個控件。

在我的情況下,我通過創建一個工廠使用UI線程中的SynchronizationContext來創建控件,然後調用CreateControl()以強制創建UI句柄來解決此問題。

Microsoft支持文章是在這裏:

0

如果您從自己的網頁,與第一CLR 2.0,然後CLR 4.0示例應用程序,那麼你會發現,這個問題似乎真的在4.0中消失 - 不知道有什麼改變,但也許他們真的解決了這個問題。 BR