猿问

跨 UI 和非 UI 线程使用 ObservableCollection

我正在使用此处描述的 SortableObservableCollection 。现在我想从 UI 或非 UI 线程操作它,所以我尝试了这里描述的解决方案:


using System;

using System.Collections.Generic;

using System.Collections.ObjectModel;

using System.Linq;

using System.Runtime;

using System.Windows.Data;


public class SortableObservableCollection<T> : ObservableCollection<T>

{

    private object _itemsLock = new object();


    public SortableObservableCollection()

        : base()

    {

        BindingOperations.EnableCollectionSynchronization(this, _itemsLock);

    }


    public SortableObservableCollection(List<T> l) : base(l)

    {

        BindingOperations.EnableCollectionSynchronization(this, _itemsLock);

    }


    public SortableObservableCollection(IEnumerable<T> l) : base(l)

    {

        BindingOperations.EnableCollectionSynchronization(this, _itemsLock);

    }

    #region Sorting


    public void Sort<TKey>(Func<T, TKey> keySelector)

    {

        InternalSort(Items.OrderBy(keySelector));

    }


    public void SortDescending<TKey>(Func<T, TKey> keySelector)

    {

        InternalSort(Items.OrderByDescending(keySelector));

    }


    public void Sort<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer)

    {

        InternalSort(Items.OrderBy(keySelector, comparer));

    }


    private void InternalSort(IEnumerable<T> sortedItems)

    {

        var sortedItemsList = sortedItems.ToList();


        foreach (var item in sortedItemsList)

        {

            Move(IndexOf(item), sortedItemsList.IndexOf(item));

        }

    }

    #endregion // Sorting


    public new void Add(T item)

    {

        base.Add(item);

    }


但是 .Net 4.5.2、WPF 桌面应用程序中的这个解决方案在移除、添加和清除方法中引发异常:System.NotSupportedException : '这种类型的 CollectionView 不支持从不同于调度程序的线程更改其 SourceCollection线。'


所以,自从BindingOperations.EnableCollectionSynchronization(this, _itemsLock); 之后,我又回到使用 Application.Current.Dispatcher 方法(见下文)。机制不像上面链接的博客文章中宣传的那样工作。


我的问题是:我在第一个列表中做错了什么,还是博客文章不正确,声称线程边界总是可以通过这种机制成功跨越?下面的清单是最好的,还是有更好的解决方案来管理具有跨线程绑定的 observablecollection?


陪伴而非守候
浏览 310回答 1
1回答

泛舟湖上清波郎朗

我的问题是:我在第一个列表中做错了什么,还是博客文章不正确,声称线程边界总是可以通过这种机制成功跨越?问题是你需要BindingOperations.EnableCollectionSynchronization在 UI 线程上调用该方法,即你需要SortableObservableCollection<T>在 UI 线程上实例化你的方法才能工作。如果您不能保证集合将在 UI 线程上初始化,则应使用调度程序将所有修改数据绑定集合的操作编组回 UI 线程。调用BindingOperations.EnableCollectionSynchronization后台线程不会解决您的问题。
随时随地看视频慕课网APP
我要回答