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

在multithreadingWPF应用程序中, 无法从WPF窗口线程以外的线程更新ObservableCollection

我知道有解决方法 ,所以我的问题不是如何避免“ 这种类型的CollectionView不支持从不同于Dispatcher线程的线程更改其SourceCollection ”exception。

我的问题是, 为什么有这样的例外? 为什么不允许从任何线程进行集合更新?

就个人而言,当ObservableCollection从其他线程更改时,我认为没有任何理由阻止UI更新。 如果两个线程(包括并行线程)访问同一个对象,一个通过事件监听对象属性的更改,另一个执行更改,它将始终有效,至少在正确使用锁定的情况下。 那么,原因是什么?

首先……我感觉到你的痛苦。 Ui线程限制可能是痛苦…

为什么不能从其创建的线程以外的线程更新Ui元素?

我的问题是,为什么有这样的例外?

简而言之,历史。 Windows已经存在了一段时间,并且Gui的某些部分的工作方式嵌入在诸如COM之类的技术中……所以改变它并不是微不足道的……很容易破坏某些东西。 我确信还有很多其他问题……但是比我聪明的人需要解释它们。 我相信WPF团队真的想要消除这个限制,他们非常努力地工作……最后我认为核心操作系统更改所需的数量是不可行的……所以他们继续……老鼠。

为什么不允许从任何线程进行集合更新?

过去是否可能……制作一些线程安全的东西总会花费一些性能并增加复杂性。 在大多数情况下,应用程序不会调用multithreading访问。 重要的是要理解,在大多数情况下,微软遵循我们所做的相同规则和相同的限制。 如果他们使ObservableCollection线程安全…他们将使用我们拥有的相同工具…锁,监视器等。他们不能破坏Ui线程规则,我们可以…没有魔法……同样的规则。

我知道有解决方法,所以我的问题不是如何避免“这种类型的CollectionView不支持从不同于Dispatcher线程的线程更改其SourceCollection”exception。

没有解决方法……没有什么可以解决的。 ObservableCollection被破坏了……它不是线程安全的。 您必须创建它,或访问它,线程安全。 对于任何非线程安全的东西都是一样的……如果你需要它是线程安全的那么就这样做。 如果你正在使用线程,那么你就知道锁等等…使用它们……这就是它们的用途。

…当ObservableCollection从其他线程更改时阻止UI更新….它将始终有效,至少如果正确使用了锁….

如果正确使用锁……确切地说! 再一次,微软可能已经把这些锁定,但他们没有并且有很好的理由。 你可以把锁放进去。或者你使用其他的策略来为你提供线程安全的访问….很多选择。

.net4.0中的任务并行库提供了一些解决这些问题的新工具。 能够为任务或线程设置上下文特别有用……

  // 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有很多可以使用的工具,这使得线程变得不那么噩梦。 使用它们……它们很有趣。

我要抽烟了。

如果您的集合绑定到用户界面元素,那么这些用户界面元素正在侦听CollectionChanged事件,并且此事件将在您要更新集合的线程上引发。

所以问题在于用户界面元素,这些元素只能从创建它们的线程访问,而不能从集合本身访问。