【问题标题】:Thread safety, lists, binding and WPF线程安全、列表、绑定和 WPF
【发布时间】:2010-08-06 11:19:11
【问题描述】:

我有一个绑定到集合 (List<T>) 的 WPF ListView。它目前是从当前线程更新的,可以正常工作。

我想将更新列表的逻辑移动到一个线程中,并且我看到了一些关于线程安全和列表绑定的潜在问题。除非我打电话给NotifyPropertyChanged,否则我可以保证不会更新绑定吗? NotifyPropertyChanged 是阻塞调用还是只是将其添加到消息队列中;在这种情况下,我肯定会告诉ListView 集合已更新,但是当绑定更新时,我可能正在修改另一个线程中的集合,这将引发异常或使程序崩溃。

在这种情况下实现线程安全的最佳方法是什么?

【问题讨论】:

    标签: c# wpf multithreading data-binding concurrency


    【解决方案1】:

    INotifyPropertyChanged 不是线程安全的,它会阻塞调用线程。

    最好的?这是个好问题。我不知道。底线是,有时必须将调用编组到 UI 线程上。你什么时候做这个?

    您可以 1) 准备好所有内容,然后将其交付给 UI 线程,然后在该线程中更新 UI。或者,您可以 2) 实现 INotifyPropertyChanged 并使该事件的触发始终发生在 UI 线程上,或者 3) 您可以执行多种不同的操作之一。

    但是,通常您会希望 UI 更新一次完成(而不是一次更新,例如将单个项目添加到 ObservableCollection 时会发生这种情况)。因此,建议创建一些实现 INotifyProperty 和 CollectionChanged 的​​线程安全基类并使用它们。

    不幸的是,框架中没有任何东西可以为您做到这一点。

    【讨论】:

      【解决方案2】:

      您可以从 Dispatcher.Invoke 进行集合更新以避免这些线程问题:

      void ThreadProc()
      {
         window.Dispatcher.Invoke(() => {
            //UpdateList
         });
      }
      

      【讨论】:

      • Invoke 不是阻塞调用,不是吗?当然可以在修改列表的同时更新绑定。
      • @Chris 是同步的,但是你可以随时调用 Begin/EndInvoke。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-27
      • 1970-01-01
      • 2015-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多