在多线程WPF应用程序中,not possible从WPF窗口线程以外的线程更新ObservableCollection
。
我知道there are workarounds,所以我的问题不是如何避免“此类型的CollectionView不支持从与Dispatcher线程不同的线程更改其SourceCollection”异常。
我的问题是,为什么会出现这样的异常?为什么不允许从任何线程进行集合更新?
就个人而言,当ObservableCollection
从其他线程更改时,我认为没有任何理由阻止UI更新。如果两个线程(包括并行线程)访问同一个对象,一个通过事件监听对象属性的更改,另一个执行更改,它将始终有效,至少在正确使用锁定的情况下。那么,原因是什么?
答案 0 :(得分:15)
首先......我感觉到你的痛苦。 Ui线程限制可能很痛苦......
为什么不能从中更新Ui元素 一个不同于它的线程 创建于?
我的问题是,为什么会有这样的 异常?
简而言之,历史。 Windows已经存在了一段时间,并且Gui的某些部分的工作方式嵌入在诸如COM之类的技术中......所以改变它并不是微不足道的......很容易破坏某些东西。我确信还有很多其他问题......但是比我聪明的人需要解释它们。我相信WPF团队真的想要消除这个限制,他们非常努力地工作......最后我认为核心操作系统更改所需的数量是不可行的......所以他们继续......老鼠。
为什么不允许这样做 来自任何线程的集合更新?
过去是否可能......制作线程安全的东西总会在性能上花费一些成本并增加复杂性。在大多数情况下,应用程序不会调用多线程访问。重要的是要理解,在大多数情况下,微软遵循我们所做的相同规则和相同的限制。如果他们已经使ObservableCollection线程安全...他们会使用我们拥有的相同工具...锁,监视器等。他们不能破坏Ui线程规则我们可以...没有魔法......相同的规则。
我知道有解决方法,所以我的 问题不是如何避免“这个 CollectionView的类型没有 支持对其的改变 来自线程的SourceCollection 与Dispatcher线程不同“ 异常。
没有解决方法......没有什么可以解决的。 ObservableCollection被破坏了..它不是线程安全的。您必须创建它,或访问它,线程安全。对于任何非线程安全的东西都是一样的...如果你需要它是线程安全的那么就这样做。如果你正在使用线程,那么你就知道锁等等...使用它们......这就是它们的用途。
...阻止UI更新时 ObservableCollection已更改 其他线程....它将永远有效, 至少如果使用锁 正确....
如果正确使用锁......确实如此!再一次,微软可能已经把这些锁定,但他们没有,并且有很好的理由。你可以把锁放进去。或者你使用其他的策略来为你提供线程安全访问......很多选择。
.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有许多工具可供您使用,这使得线程变得不那么噩梦。使用它们......它们很有趣。
我要抽烟了。
答案 1 :(得分:10)
如果您的集合绑定到用户界面元素,那些用户界面元素正在侦听集合的CollectionChanged
事件,并且此事件将在您正在更新集合的线程上引发。
问题在于用户界面元素,这些元素只能从创建它们的线程访问,而不能从集合本身访问。