2011-08-11 66 views
4

我已經看到(並閱讀)使用Dispatcher.BeginInvoke確保UI更新發生在UI線程上。我理解這個推理。爲什麼要使用Dispatcher.BeginInvoke?

但我已經看到了在視圖代碼隱藏中爲TextBlock分配屬性(如Text屬性)的示例,只有在您將其分配到此Dispatcher.BeginInvoke中時才被聲明爲安全。

問題 如果我操縱從視圖中的代碼隱藏任何東西,是不是意味着它被UI線程操作(假設我不使用一個BackgroundWorker或異步服務調用)。

在上面提到的例子中,沒有使用其他線程或異步操作。

問題2 如果我有一個異步Web服務處理程序,並且我想從此處理程序中更新TextBlock的字符串。我可以直接指定TB的Text屬性,還是應該使用Dispatcher.BeginInvoke。請注意,我不會這樣做,因爲我喜歡通過直接UI元素操作進行數據綁定。

+0

請參閱我的編輯 – AnthonyWJones

回答

3

您問「這是不是暗示它正在UI線程上操作」。沒有任何東西給出絕對的保證,因爲Mike指出非私有代碼入口點可能會在非UI線程上調用。

但是,您可以確定從UI元素到達的事件將在UI線程上。

至於採取任何預防措施以確保您的代碼隱藏在UI線程上運行,我不認爲這是明智的。如果你讓代碼正常進行會發生什麼。可能它成功了,因爲你實際上沒有與UI元素交互,沒有造成任何傷害。另外代碼繼續並拋出一個異常。那不好嗎?

使用預防性BeginInvoke會導致調用代碼與調用的UI操作代碼異步完成。這可能會有不可預測的結果,可能是追查的噩夢。讓代碼具有可預測性是更好的選擇。只需將錯誤返回到應該負責在正確線程上調用UI組件的代碼。在全部代碼隱藏作爲UI組件的一部分運行之後,例如UserControlPage

還要考慮運行時,SDK和工具包中的現有UI元素不會執行預防性線程切換。

編輯:答案面露此外,第二個問題

這取決於你所使用的API被稱爲對異步API和什麼的線程。

當您從UI線程調用WebClient異步方法時,也會在UI線程上引發相應的事件。同樣,如果您使用的是WCF服務客戶端類,則在UI線程上如果最初在UI線程上調用異步操作,則會引發Completed事件。

但是,在WebRequest組件(或來自WCF的標準服務接口)上使用Begin/End對時,回調將在後臺線程上運行,而不管用於啓動操作的原始線程。

0

如果它是一個只響應UI事件的受保護方法或事件處理程序,那麼在沒有調度程序的情況下應該是安全的。但是,如果您的代碼可以以任何方式在外部暴露,那麼最好不要對它可能執行的線程做任何假設。

+0

對我來說完全有意義的是,UI元素事件處理程序(即Clicked事件)中的直接UI元素操作是安全的。這在我提到的例子中讓我感到困惑,因爲它們太簡單了,我看不出有可能是UI線程相關異常。 – AlvinfromDiaspar