2009-11-24 89 views
1

我正在嘗試創建一個自定義的內部應用程序,該應用程序將訪問通過UDP廣播其名稱和IP地址的其他內部系統。我試圖創建一個多線程對話框,每隔500毫秒輪詢UDP消息15秒,解析UDP消息,然後將檢測到的系統的名稱添加到對話框中的列表框中,實時更新它。我已經測試並完成了UDP掃描代碼,唯一的問題是跨線程更新ListBox。任何時候我嘗試訪問ListBox的Items或ItemSource屬性時,都會得到System.InvalidOperationException:「調用線程無法訪問此對象,因爲不同的線程擁有它。」多線程訪問C#中的WPF GUI#

相關的堆棧跟蹤部分:

at System.Windows.Threading.Dispatcher.VerifyAccess() 
    at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value) 
    at System.Windows.Controls.ItemsControl.set_ItemsSource(IEnumerable value) 

這不管我是否使用一個ObservableCollection發生(我知道,無關與集合型),一個HashSet或任何其他對象。任何人都可以幫助我跨不同線程訪問GUI嗎?

回答

5

您無法從其他線程安全地訪問gui。所有調用都必須通過調用調用來在主線程上執行。這是Windows多年來一直困擾着的遺留問題。

這裏的代碼片段應該讓你開始... (這裏找到:http://social.msdn.microsoft.com/forums/en-US/wpf/thread/360540eb-d756-4434-86f9-a3449f05eb55/

if(textbox.Dispatcher.CheckAccess()) 
{ 
    // The calling thread owns the dispatcher, and hence the UI element 
    textbox.AppendText(...); 
} 
else 
{ 
    // Invokation required 
    textbox.Dispatcher.Invoke(DispatcherPriority.Normal, [delegate goes here]); 
} 

有額外的澄清一下:http://channel9.msdn.com/forums/TechOff/251835-WPF-Invoke-and-Anonymous-delegates/

+0

哇,這是一個非常有用的答案,它做到了。非常感謝。如果可以的話,我可以多投一遍你的答案。 – 2009-11-24 19:52:48

+0

另請注意,您也可以使用Dispatcher.BeginInvoke/EndInvoke模式異步調度回UI線程 – 2009-11-26 00:52:44

2

安德魯已經說了,你應該同步跨線程訪問GUI(這只是它的方式 - 你不能做太多的事情)。

但是,Dispatcher是一個WPF特定的同步機制。如果你想堅持更一般的方法,那麼請看System.Threading.SynchronizationContext課。