首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >从哪里可以获得线程安全的CollectionView?

从哪里可以获得线程安全的CollectionView?
EN

Stack Overflow用户
提问于 2010-01-26 14:12:57
回答 12查看 36.2K关注 0票数 68

在后台线程上更新业务对象集合时,我收到以下错误消息:

此类型的CollectionView不支持从不同于Dispatcher线程的线程更改其SourceCollection。

好的,这是有道理的。但它也回避了一个问题,什么版本的CollectionView支持多线程,以及如何让我的对象使用它?

EN

回答 12

Stack Overflow用户

回答已采纳

发布于 2012-09-04 08:32:28

以下是对Jonathan发现的实现的改进。首先,它在与之关联的dispatcher上运行每个事件处理程序,而不是假设它们都在同一个(UI) dispatcher上。其次,它使用BeginInvoke来允许在我们等待dispatcher变得可用时继续处理。这使得在后台线程在每个线程之间进行大量更新和处理的情况下,解决方案变得更快。也许更重要的是,它克服了等待调用时阻塞所导致的问题(例如,在ConcurrencyMode.Single中使用WCF时可能会发生死锁)。

代码语言:javascript
复制
public class MTObservableCollection<T> : ObservableCollection<T>
{
    public override event NotifyCollectionChangedEventHandler CollectionChanged;
    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        NotifyCollectionChangedEventHandler CollectionChanged = this.CollectionChanged;
        if (CollectionChanged != null)
            foreach (NotifyCollectionChangedEventHandler nh in CollectionChanged.GetInvocationList())
            {
                DispatcherObject dispObj = nh.Target as DispatcherObject;
                if (dispObj != null)
                {
                    Dispatcher dispatcher = dispObj.Dispatcher;
                    if (dispatcher != null && !dispatcher.CheckAccess())
                    {
                        dispatcher.BeginInvoke(
                            (Action)(() => nh.Invoke(this,
                                new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))),
                            DispatcherPriority.DataBind);
                        continue;
                    }
                }
                nh.Invoke(this, e);
            }
    }
}

因为我们使用的是BeginInvoke,所以在调用处理程序之前,通知的更改可能会被撤消。这通常会导致"Index in out of range“。当根据列表的新(更改)状态检查事件参数时,将引发异常。为了避免这种情况,所有延迟的事件都将替换为重置事件。在某些情况下,这可能会导致过多的重绘。

票数 64
EN

Stack Overflow用户

发布于 2010-12-16 22:18:52

使用:

代码语言:javascript
复制
System.Windows.Application.Current.Dispatcher.Invoke(
    System.Windows.Threading.DispatcherPriority.Normal,
    (Action)delegate() 
    {
         // Your Action Code
    });
票数 88
EN

Stack Overflow用户

发布于 2010-01-26 15:04:10

Bea Stollnitz的This帖子解释了错误消息以及为什么它是这样表达的。

编辑:来自Bea博客的

不幸的是,此代码导致异常:“NotSupportedException-此类型的CollectionView不支持从不同于Dispatcher线程的线程更改其SourceCollection。”我理解这个错误消息会让人们认为,如果他们使用的CollectionView不支持跨线程更改,那么他们必须找到支持跨线程更改的那个。好吧,这个错误消息有点误导:我们提供的开箱即用的CollectionViews都不支持跨线程的集合更改。不幸的是,我们现在还不能修复这个错误信息,我们已经被锁定了。

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2137769

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档