C# BindingOperations.EnableCollectionSynchronization和CollectionChanged在多线程WPF应用程序中的交互

C# BindingOperations.EnableCollectionSynchronization和CollectionChanged在多线程WPF应用程序中的交互,c#,wpf,multithreading,C#,Wpf,Multithreading,我正在尝试开发一个多线程WPF应用程序。作为其中的一部分,我正在使用 BindingOperations.EnableCollectionSynchronization( IEnumerable collection, object context, CollectionSynchronizationCallback synchr

我正在尝试开发一个多线程WPF应用程序。作为其中的一部分,我正在使用

BindingOperations.EnableCollectionSynchronization(
                            IEnumerable collection,
                            object context,
                            CollectionSynchronizationCallback synchronizationCallback)
。。。避免工作线程更新ListView而导致异常

当ObservableCollection在工作线程上引发CollectionChanged时,上述操作将确保转换到UI线程

您可以按如下方式实现自己的同步回调锁定:

protected void synchronizationCallback(
            IEnumerable collection,
            object context,
            Action accessMethod,
            bool writeAccess)
{
    ReaderWriterLockSlim listLock = context as ReaderWriterLockSlim;

    if (writeAccess)
    {
        listLock.EnterWriteLock();

        accessMethod();

        listLock.ExitWriteLock();                

        return;
    }

    listLock.EnterReadLock();

    accessMethod();

    listLock.ExitReadLock();
}
但是为了避免递归锁,我发现我需要在引发CollectionChanged之前退出ObservableCollection锁

因此,在synchronizationCallback中遇到锁之前,另一个工作线程可能会进入ObservableCollection。因此,.NET Framework代码如果需要读取ObservaleCollection,最终可能会读取与NotifyCollectionChangedEventArgs中通知的状态不同的状态


然而,这是一个问题吗?我的想法是否定的,因为ListView将在稍后的状态下更新。

是的,这是一个问题-您可能会遇到“在OnCollectionChanged事件期间无法更改集合”异常,因为在第二个工作线程尝试更改集合状态之前,该事件可能尚未完成。

请参见备注4。
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
    Debug.Assert(!this.listLock.IsReadLockHeld);
    Debug.Assert(this.listLock.IsWriteLockHeld);

    this.listLock.ExitWriteLock();

    base.OnCollectionChanged(e);

    this.listLock.EnterWriteLock();
}