【问题标题】:Multithreaded access to the WPF GUI in C#在 C# 中多线程访问 WPF GUI
【发布时间】:2009-11-24 18:52:26
【问题描述】:

我正在尝试创建一个自定义的内部应用程序,该应用程序将访问通过 UDP 广播其名称和 IP 地址的其他内部系统。我正在尝试创建一个多线程对话框,该对话框每 500 毫秒轮询一次 UDP 消息,持续 15 秒,解析 UDP 消息,然后将检测到的系统的名称添加到对话框中的 ListBox 中,实时更新它。我已经测试并完成了 UDP 扫描代码,唯一的问题是跨线程更新 ListBox。每当我尝试访问 ListBox 的 Items 或 ItemSource 属性时,都会收到 System.InvalidOperationException :“调用线程无法访问此对象,因为不同的线程拥有它。”

相关的堆栈跟踪部分:

   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 吗?

【问题讨论】:

    标签: c# wpf multithreading


    【解决方案1】:

    您无法从其他线程安全地访问 gui。所有调用都必须通过调用 Invoke 来分派,以便在主线程上执行。这是 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/

    【讨论】:

    • 哇,这是一个非常有用的答案,而且成功了。太感谢了。如果可以的话,我会再对你的答案投票十几次。
    • 另请注意,您也可以使用 Dispatcher.BeginInvoke / EndInvoke 模式异步分派回 UI 线程
    【解决方案2】:

    正如 Andrew 已经说过的,您应该跨线程同步对 GUI 的访问(这就是它的方式 - 您对此无能为力)。

    但是,Dispatcher 是 WPF 特定的同步机制。如果您想坚持更通用的方法,请查看System.Threading.SynchronizationContext 类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多