2009-04-14 18 views

回答

28

從非UI線程我們無法觸及用戶界面 - 非常糟糕的事情可能發生,因爲控件具有線程親和力。因此,從非UI線程,我們必須(至少)呼叫InvokeBeginInvoke

對於UI線程,但是 - 我們不要想要撥打Invoke很多時間;問題是如果你已經在UI線程上,它仍然有不必要的消息發送消息到表單的泵並處理它。

在現實中,大多數線程代碼,你知道你希望被稱爲在 -UI螺紋上的特定方法,所以在這種情況下,沒有額外的開銷,只要調用:Invoke

+1

你知道我們在說話多長時間嗎?我假設有一個,但我猜測它的<0.5秒,在大多數GUI中我會說是可以接受的(有些人可能會不同意) 我假設Control.Invoke不會因性能原因檢查InvokeRequired本身嗎? – MattH 2009-04-14 16:25:05

+1

哦,絕對<0.5s - 儘管你當然可以這麼做(例如,10000通話)。 – 2009-04-15 05:44:06

2

InvokeRequired基本上告訴你,如果你正在執行正確的線程或沒有。如果你不在正確的線程上,你需要將任務編組到正確的線程,否則你不需要。因此需要檢查。

0

Invoke將通過Delegate調用代碼,而不是直接進行代價很高的代碼。

它的成本效益只有在需要時調用Invoke。因此,InvokeRequired用於發現是由相同的線程或另一個線程進行的調用?

0

我能想到的一個原因就是性能。 如果大多數情況下調用線程與創建線程相同,那麼您將有一些不確定的開銷。

1

問題是GUI控件有一個要求,即只有在用於實例化GUI控件的同一線程上執行的代碼才能訪問GUI控件。這個要求背後的原因與Windows的體系結構有關。完全可以說,要改變這一點非常困難。

InvokeRequired根據實例化線程的標識檢查當前執行線程的標識。如果它們相同,則代碼可以與控件自由交互。否則,代碼必須將數據從當前線程整理到實例化線程。這是一個緩慢而昂貴的過程,如果可能的話應儘量避免。如果您始終調用代碼,並且可能不會注意到性能受到影響,但在多核系統投入使用時,這種情況將越來越普遍。最好不要創建稍後需要撤消的代碼「節點」。

1

如果您在創建窗口句柄之前嘗試調用(例如調用窗體構造函數時),您將得到一個InvalidOperationException。所以,一般需要InvokeRequired檢查。詳情請參閱MSDN