2008-08-13 123 views

回答

10

因爲你可以很容易地結束死鎖(以及其他問題)。

例如,您的輔助線程可能會嘗試更新UI控件,但UI控件將等待被釋放的輔助線程鎖定的資源,因此兩個線程都會最終等待對方完成。正如其他人所評論的,這種情況並不是UI代碼所特有的,而是特別常見。

在其他語言如C++,你可以自由嘗試做到這一點(沒有被拋出在WinForms的除外),但您的應用程序可能會凍結,停止應該死鎖發生響應。

順便說一句,你可以很容易地告訴你要更新控制UI線程,只要創建一個委託,然後調用(異步)BeginInvoke方法對控制傳遞給它的委託。例如。

myControl.BeginInvoke(myControl.UpdateFunction); 

這是相當於1.0/1.1也不例外,從一個工作線程做C++/MFC PostMessage的

+3

我不知道爲什麼這個答案被接受。這根本不是正確的答案。只要你有多個線程就會發生死鎖。 GUI程序中沒有任何固有的東西可以使它們更有可能發生。而且,即使使用BeginInvoke(),它們也很容易發生。 Brian Ensink的答案是正確的。 – mhenry1384 2010-10-06 19:54:31

+1

-1:等待鎖定的資源不是問題。問題在於競爭條件,在任何代碼中大量存在的設計不適用於多線程環境。您甚至可以通過將[CheckForIllegalCrossThreadCalls](http://msdn.microsoft.com/en-us/library/system.windows.forms.control.checkforillegalcrossthreadcalls(VS.80).aspx)設置爲false來檢查此問題,並觀察死鎖免費的操作,直到有趣的事情發生。 – 2011-01-15 11:59:10

1

這樣,你就沒有兩件事情要同時更新控件。 (如果CPU在寫入/讀取過程中切換到另一個線程,則可能發生這種情況) 當訪問多個線程之間的共享變量時,需要使用互斥鎖(或其他同步)的原因相同。

編輯:

在其他語言如C++你 免費嘗試做到這一點(沒有 拋出異常,如 的WinForms),但你最終會學習 硬辦法!

稀釋是...我的C/C++和C#,因此之間切換是有點更通用的話,我應該去過,對不起......他是正確的,你可以在C/C++,但它會回來咬你!

2

回到調試過程中被拋出,你得到的卻是間歇運行時掛方案。太好了! :) 因此,2.0他們使這種情況下拋出一個異常,非常正確。

的實際原因可能是(亞當海爾州)某種併發/ locky問題。 請注意,正常的.NET api(如TextBox.Text =「Hello」;)會包裝SEND命令(需要立即採取措施),如果在執行更新操作的單獨線程上執行該命令,則會產生問題。使用Invoke/BeginInvoke會使用一個POST來替代這個動作。

有關SEND和POST的更多信息here

1

還需要在更新函數中實現同步,這些更新函數對同時被調用敏感。對於UI元素來說,這樣做在應用程序和操作系統級別都會很昂貴,而且絕大多數代碼都是完全冗餘的。

一些API提供了一種方法來更改系統的當前線程所有權,以便您可以暫時(或永久)從其他線程更新系統而無需訴諸線程間通信。

0

我認爲這是一個很好的問題 - 我認爲需要更好的答案。

當然,唯一的原因是某個框架中有某些東西不是非常安全的。這是.NET或Win32的問題 - 爲什麼沒有推動修復源代碼而不是強制執行對我來說感覺像是一個討厭的解決方法?

任何人都知道真正的潛在問題在哪裏?

23

我認爲這是一個輝煌的問題 - 我覺得有需要更好的 答案。

當然,唯一的原因是有 是某個地方 是不是很線程安全的東西。

「something」幾乎是System.Windows.Forms中每個控件上的每個單個實例成員。

System.Windows.Forms中許多控件的MSDN文檔(如果不是全部),則說「此類型的任何公共靜態(在Visual Basic中爲Shared)成員都是線程安全的。是線程安全的。「

這意味着實例成員如TextBox.Text {get; set;}折返

使這些實例成員中的每個成員都是線程安全的可能會引入大量應用程序不需要的大量開銷。相反,.Net框架的設計者決定,並且我認爲正確的做法是,應該將同步來自多個線程的表單控件的訪問同步的負擔放在程序員身上。

[編輯]

儘管這個問題只問「爲什麼」這裏是一個鏈接,解釋了一篇「如何」:

如何:使線程安全的調用到Windows窗體控件 MSDN上

http://msdn.microsoft.com/en-us/library/ms171728.aspx

7

雖然聽起來合理約翰答案是不正確的。事實上,即使使用Invoke,您仍然不安全,不會進入死鎖狀態。當使用Invoke處理在後臺線程上觸發的事件時,甚至可能導致此問題。


真正的原因更多的是與比賽條件和古老的Win32時代奠定了回來。我無法在這裏解釋細節,關鍵字是消息泵,WM_PAINT事件以及「發送」和「POST」之間的細微差別。


進一步的信息可以在這裏herehere發現。

0

嗯我不是很確定,但我認爲當我們有進度控制像等待酒吧,進度條時,我們可以從另一個線程更新他們的值,一切都很好,沒有任何毛病。

相關問題