2009-11-24 91 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课。