回答
根據不同的情況有不同的選項:
從另一個線程
例如訪問控制用進度信息更新TextBlock。
-
在這種情況下,你可以做最簡單的事情是避免與控制的直接互動。您只需要bind您想要訪問或修改的對象的類別implements
INotifyPropertyChanged
然後設置該對象的屬性。該框架將爲您處理剩下的事情。 (通常情況下,您很少需要直接與UI元素交互,您幾乎總是可以綁定相應的屬性並使用綁定源代替;可能需要直接控制訪問的一種情況是控制創作)。在某些情況下,當試圖修改綁定ObservableCollection<T>
,爲此,你需要單獨的數據綁定是不夠的,例如... -
你可以派遣您的訪問代碼的線程擁有這個對象,可以通過調用來完成或
BeginInvoke
的Dispatcher
擁有正在訪問的對象(在另一個線程上獲得此Dispatcher
是可能的)。例如
new Thread(ThisThreadStart).Start();
void ThisThreadStart() { textBlock.Dispatcher.Invoke(new Action(() => textBlock.Text = "Test")); }
如果不執行的線程的方法上明顯可以使用
Dispatcher.CheckAccess
要麼派遣或直接執行操作。例如
void Update() { Action action =() => myTextBlock.Text = "Test"; var dispatcher = myTextBlock.Dispatcher; if (dispatcher.CheckAccess()) action(); else dispatcher.Invoke(action); }
如果一個對象不是
DispatcherObject
,你仍然需要相關Dispatcher
可以使用Dispatcher.CurrentDispatcher
在線程創建對象(所以這樣的方法,通過一個線程執行不會對你有任何好)。爲了方便,您通常在應用程序的主UI線程上創建對象;你可以從任何地方使用Application.Current.Dispatcher
獲得該線程的Dispatcher
。
特殊情況:
-
移動,它會在創建實例(當然這應該是UI線程的線程上
ProgressChanged
任何控制訪問) 定時器
在WPF中你可以使用
DispatcherTimer
爲了方便,它分派給你,讓在Tick
任何代碼調用的相關調度。如果您可以將調度委託給數據綁定系統,那麼您當然也可以使用普通定時器。
你可以閱讀更多關於Dispatcher
隊列如何工作和WPF一般on MSDN線程。
訪問在另一個線程上
例如創建的對象在後臺加載圖像。
如果有問題的對象不是Freezable
你應該在一般只需避免對另一個線程創建它或限制訪問創建線程。如果是Freezable
,您只需撥打Freeze
即可讓其他線程訪問它。
從另一個線程
即,其實例被更新是用戶代碼的類型訪問的數據對象。如果拋出異常,這種情況可能是由某人使用DependencyObject
作爲數據類的基本類型。
這種情況與訪問控制的相同,可以應用相同的方法,但通常應該首先避免它。當然,這允許通過dependency properties簡單的屬性更改通知,這些屬性也可以綁定,但往往不夠,這是不值得放棄線程獨立性。您可以從INotifyPropertyChanged
獲得更改通知,並且WPF中的綁定系統本質上是不對稱的,始終存在綁定的屬性(目標)以及此綁定的來源。通常,UI是目標,數據是源,這意味着只有UI組件應該需要依賴項屬性。
這將是代碼幾百行,什麼東西我「想通了」。
但摘要:
App_OnStartup 生成後臺線程
回調,
呼叫
Application.Current。MainWindow.Dispatcher.CheckAccess() - 得到異常 Application.Current.Dispatcher.CheckAccess()不是
問題是'Current.MainWindow'步驟,而不是'MainWindow.Dispatcher',所以是的,這不是我所暗示的...... – 2013-12-07 22:04:51
正如我想通的,但給定的MainWindow和Dispatcher不是null,你會期望一種旨在告訴您跨線程訪問是否安全的方法不會引發交叉線程異常 – 2013-12-08 23:37:15
我有一個udp監聽器對象,它通過事件進行通信,其中方法/回調是在我的mainWindow中編輯的wpf .cs文件。
事件處理函數被調用的參數,一個是我想在mainWindow.cs
在這個線程由H.B.使用信息顯示在一個列表框消息以上; 我已經加入,測試和使用下面的代碼來處理在WPF中crossthread在我的事件處理程序的回調,但我用一個真實的消息不是一個硬編碼之一:
listBox1.Dispatcher.Invoke(new Action(() => listBox1.Items.Add("MessageHere")));
UPDATE:
這是更好,因爲你可以把更多的東西放在匿名函數中。
listBox1.Dispatcher.Invoke((Action)delegate
{
listBox1.Items.Add(e.ReaderMessage);
});
- 1. 跨線程訪問異常:如何實現?
- 2. 多線程異常處理
- 3. Boost線程異常處理
- 4. 線程和異常處理
- 5. 線程異常處理
- 6. 跨線程異常
- 7. 在全局異常處理程序中處理線程異常?
- 8. 如何在ASP.NET中處理未處理的線程異常?
- 9. 如何訪問Spring MVC異常處理程序中的@PathVariable?
- 10. 跨線程的C++同步和異常處理
- 11. 非法跨線程操作異常,無法處理它
- 12. 如何處理Python的線程。線程異常?
- 13. 修復跨線程異常
- 14. 跨線程調用異常
- 15. 跨線程異常拋出
- 16. BindingSource和跨線程異常
- 17. 週期性任務中無效的跨線程訪問異常
- 18. PerformanceProgressBar「無效的跨線程訪問」異常
- 19. 如何線程的異常傳播迴應用程序異常處理程序
- 20. asp.net背景線程異常處理
- 21. 內部線程異常處理
- 22. std ::線程和異常處理
- 23. Python的線程未處理的異常
- 24. 無法處理線程內的異常
- 25. 處理WCF中的線程異常
- 26. 線程中的異常處理
- 27. 處理異常的Python線程池
- 28. 捕獲未處理的線程異常
- 29. 何時期待`跨線程異常'?
- 30. 水線處理異常
那麼這裏是一個愚蠢的問題呢。 Dispatcher.CheckAccess()會引發什麼?「調用線程不能訪問這個對象,因爲不同的線程擁有它」? – 2013-12-05 23:30:43
@RogerWillcocks:從未發生過我。舉一個完整的例子來重現這一點... – 2013-12-06 02:32:52
Application.Current.Dispatcher.Invoke(new Action((=)textBox.Text =「Test」));完美工作!謝謝! – 2017-06-16 15:46:00