2014-09-24 60 views
0

我有一個工人類和MainForm/UI類。在UI類中,我在新的後臺線程中創建了Worker類的新實例。這個線程將一些更新集中回UI控件。由於它們在不同的類中,我基本上將MainForm實例(this)和適當的委託傳遞給worker類的構造函數來更新控件。在構造函數中,我將mainForm設置爲一個ISynchronizeInvoke對象(稱之爲_synch),然後在工作者類中進一步向下,我做了_synch.Invoke(theDelegate, new object[] { "new value" })ISynchronizeInvoke VS SynchronizationContext與mainForm.Invoke

這一切工作正常,但後來我意識到,它也可以做簡單的mainForm.Invoke(不使用ISynchronizeInvoke對象)。兩者有什麼區別?

更糟糕的是,我讀了一篇文章,認爲ISynchronizeInvoke不再需要太多了,現在SynchronizationContext已經很長了。我意識到我不明白這兩者是什麼。任何幫助理解爲什麼我應該使用這些對象的調用,而不是直接在mainForm上,將不勝感激。

+0

ISynchronizeInvoke僅僅是有用的,做其他庫*不*有任何想法,這特別的線程是UI線程或如何正確調用來操縱UI代碼。從來沒有與類的問題,它*是用戶界面。並實現使ISynchronizeInvoke工作的管道。令人遺憾的是,WPF違反了合同,因此它不再是一個通用界面。 – 2014-09-24 16:45:35

+0

@HansPassant感謝Hans。我嘗試按照Sriram的建議切換到'SynchronizationContext',但Send和Post不接受自定義代理。他們採用只有一個參數的SendOrPostCallback委託('object')。我當前的自定義委託具有值字符串(我希望標籤採用的文本)和字符串lbName,以便該方法可以識別要更新的標籤控件。你推薦我在這裏做什麼?我應該堅持Form.Invoke嗎?謝謝! – Anders 2014-09-24 16:58:42

+0

99%的時間使用Invoke是錯誤的。非常容易出現死鎖和比賽,總是使用BeginInvoke。單個對象足以存儲*任何內容*,如有必要,可使用小型輔助類。拉姆達幾乎總是方便的選擇。 – 2014-09-24 17:05:59

回答

4

在Winforms中,不管你用什麼方法調用Form.Invoke,ISynchronizeInvoke.Invoke,SynchronizationContext.Send你都在做同樣的事情。

事實上,他們都在內部採取相同的方法,即Control.Invoke(實現接口成員ISynchronizeInvoke)。

兩者(Form.Invoke和ISynchronizeInvoke.Invoke)有什麼區別?

沒什麼,他們指向相同的方法Control.Invoke

也就是說,如果你依賴於ISynchronizeInvoke,當你將應用程序移植到另一種技術(比如說WPF)時,你會感到很痛苦。那裏不支持ISynchronizeInvoke。這是WinForms的具體事情。你應該始終贊成SynchronizationContext

SynchronizationContext提供了抽象,不管技術如何,您可以通過SynchronizationContext來編組對UI線程的調用(通常不總是)。如果您的代碼依賴於SynchronizationContext,則可以輕鬆地移植到WPF或Asp.Net,因爲它們提供了SynchronizationContext的技術特定實現。

  • 的WinForms實現 - WindowsFormsSynchronizationContext
  • WPF/Silverlight實現 - DispatcherSynchronizationContext
  • Asp.net實現 - AspNetSynchronizationContext

一個SynchronizationContext缺點是,它沒有提供的方式來獲得返回值,儘管你可以通過閉包,實例成員等來解決它。

延伸閱讀:It's All About the SynchronizationContext

+0

謝謝!所以我會忘記ISynchronizeInvoke。關於使用Form.Invoke ,缺點是Form.Invoke不會工作,如果我切換到WPF(即使那裏的控件具有相同的名稱)? – Anders 2014-09-24 15:29:46

+0

我得到這個錯誤的構造函數,如果我嘗試使用SynchronizationContext作爲對象:'不能兌換 源類型MainForm爲目標類型SynchronizationContext'。任何想法? – Anders 2014-09-24 15:34:23

+0

@Anders你不能在wpf中使用相同的控件。您將使用wpf特定的等效控件。雖然您可以在wpf中使用[Dispatcher.Invoke](http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.invoke%28v=vs.110%29.aspx),那意味着你需要修改你的代碼。如果使用'SynchronizationContext',它將按原樣運行。 – 2014-09-24 15:34:53

相關問題