2016-08-11 62 views
2

很可能我的問題一般無法得到解答,如果是的話,無論如何這都是有趣的信息。我試圖更好地理解UI控件交互,特別是非UI線程執行什麼和什麼是不允許的。在我的情況下,我正在與WPF控件和位於Microsoft.Office.Interop命名空間中的對象(代表控件)進行交互。我在模型圖層中的後臺線程上做了很多工作,但是當我的視圖模型中接收到事件時,我正在調度UI線程(通常在使用綁定到WPF控件的屬性時) 。這對我來說是有意義的,它似乎運作良好。然而,我不確定後臺線程可以做什麼和不能做什麼。本質上,我試圖瞭解邊界在哪裏。爲了發揮想象力,請參閱下面的一些問題。我明白我的要求有些開放式,所以如果有人知道我可以閱讀的外部資源,那對我來說也是一樣的好。UI線程vs後臺線程 - UI控件可訪問性邊界

  • 我可以get()從後臺線程綁定到用戶界面的屬性,即是隻set()必須從UI線程來完成?
  • 如果我有一個互操作對象,比如說Microsoft.Office.Interop.Slide,在我看來,我必須在UI線程上與它交互,因爲它是一個實際的UI控件。但是,我可以聽聽在非UI線程中返回這些對象的事件嗎?我可以從非UI線程檢查幻燈片爲null嗎?對於來自非UI線程的Slide類型中包含的屬性,我可以嗎?

總之,在後臺線程和UI線程之間切換時,我能記住一條好規則嗎?例如「更改必須在UI線程上完成的任何動作」或「直接交互的任何動作,而不管動作(例如檢查是否爲null)必須在UI上完成線」。

回答

2

任何與UI交互不是線程安全的,試圖削減角落會給你帶來麻煩。你可能認爲一個財產獲得者是無辜的,但事實並非如此。當用戶在線程運行時繼續與UI進行交互時,沒有什麼事情發生,您將計算一個陳舊值的結果並顯示與UI狀態不一致的結果。你會知道不會改變對線程所做的事情至關重要的價值,你的用戶不會這樣做。

沒有鎖定可以解決這個問題,你不能在UI線程中放置一個鎖,並且你不能對用戶進行鎖定。除了顯而易見的之外,您需要編寫代碼,以防止用戶在線程滾動時更改值。現在,它使得在線程內部獲得值非常沒有必要,您可能還需要在啓動線程之前獲取它。 lambda表達式非常方便將其傳遞給線程代碼。

您當然可以可以允許用戶更改UI,但是您必須編寫更復雜的線程代碼。您必須確保當前線程停止並且新線程啓動,現在使用更新後的值。很難做到正確,線程停止不是瞬時的,容易陷入僵局。

同樣適用於線程的結果,在線程內更新UI通常沒有意義。 BackgroundWorker和Task類可以幫助您在線程完成後在UI線程上啓動代碼,它可以安全地更新UI的結果。讓線程做一些容易想到且易於互鎖的小東西,對於避免麻煩非常重要。

Office interop與WPF有點不同,在COM中線程安全是自動的。它自動調用Dispatcher.Invoke()的等價物,不需要額外的幫助。在工作線程運行時,Office文檔更可能保持靜態。除了允許用戶更改文檔之外,您還可以將getter問題帶回黑桃。因人而異。

+0

感謝漢斯,我會接受你的回答。清理爲什麼屬性獲取者可能會危險地調用工作線程特別有用! –