wpf 为什么不能从不同的线程更新ObservableCollection?

xtfmy6hx  于 2023-10-22  发布在  其他
关注(0)|答案(2)|浏览(184)

在多线程WPF应用程序中,从WPF窗口线程以外的线程更新ObservableCollectionnot possible
我知道there are workarounds,所以我的问题不是如何避免“This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread”异常。
我的问题是,为什么会有这样的例外?**为什么不允许从任何线程更新集合?
就我个人而言,我不认为有任何理由阻止UI更新时,ObservableCollection是从其他线程更改。如果两个线程(包括并行线程)正在访问同一个对象,一个通过事件监听对象属性的更改,另一个进行更改,它将始终工作,至少在正确使用锁的情况下。那么,原因何在?

wa7juj8i

wa7juj8i1#

首先...我感受到了你的痛苦Ui线程限制可能是一个痛苦.
为什么不能从创建Ui元素的线程以外的线程更新Ui元素?
我的问题是,为什么会有这样的例外?
简而言之,历史。Windows已经存在了一段时间,GUI的某些部分工作方式嵌入到COM等技术中......所以改变它并不容易......很容易破坏某些东西。我相信还有很多其他的问题......但比我聪明的人需要解释它们。我相信WPF团队真的很想删除这个限制,他们工作得很努力..
为什么不允许从任何线程更新集合?
无论过去还是现在...使某些东西线程安全总是会在性能上付出一些代价,并增加复杂性。在大多数情况下,应用程序不调用多线程访问。重要的是要明白,在大多数情况下,微软遵循与我们相同的规则和相同的限制。如果他们让ObservableCollection成为线程安全的.他们会使用我们拥有的相同工具.锁,监视器等。他们不能打破Ui线程规则,就像我们不能一样......没有魔法......同样的规则。
我知道有解决方法,所以我的问题不是如何避免“这种类型的CollectionView不支持从与Dispatcher线程不同的线程对其SourceCollection的更改”异常。
没有变通办法...没有变通办法。ObservableCollection被破坏了,它不是线程安全的。您必须使它或对它的访问成为线程安全的。这对于任何不是线程安全的东西都是一样的.如果你需要它是线程安全的,那么就这样做。如果你正在使用线程,那么你知道关于锁和这样的东西...使用它们...这就是它们的用途。
.当ObservableCollection从其他线程更改时阻止UI更新.它总是会起作用的,至少如果锁使用得当的话。
如果锁使用得当...没错!同样,微软本可以把这些锁,但他们没有,并有很好的理由。你可以把锁放进去或者你使用其他策略来给你给予线程安全访问..
.net4.0中的Task Parallel Library提供了一些新的工具来解决这些问题。能够为任务或线程设置上下文特别有用.

// get the Ui thread context
  _uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

  Action DoInBackground = new Action(() =>
  {
    /*...In the background...
      ...process some data for an ObservableCollection...*/
  });

  Action DoOnUiThread = new Action(() =>
  { 
    /*...On the UI thread...
      ...read/write data to an ObservableCollection...*/
  });

  // start the background task
  var t1 = Task.Factory.StartNew(() => DoInBackground());
  // when t1 is done run t1..on the Ui thread.
  var t2 = t1.ContinueWith(t => DoOnUiThread(), _uiScheduler);

不要把Ui Elements的线程关联需求看作是需要解决的问题.
C#和.Net有许多工具可以使用,使线程少一点噩梦。使用它们,它们可以很有趣。
我去抽根烟。

lnxxn5zx

lnxxn5zx2#

如果您的集合绑定到用户界面元素,则这些用户界面元素将侦听集合的CollectionChanged事件,并且此事件将在您正在更新集合的线程上引发。
因此,问题出在用户界面元素上,这些元素只能从创建它们的线程访问,而不能通过集合本身访问。

相关问题