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

时间:2015-01-29 10:45:18

标签: c# wpf multithreading

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

BindingOperations.EnableCollectionSynchronization(
                            IEnumerable collection,
                            object context,
                            CollectionSynchronizationCallback synchronizationCallback)

...以避免工作线程更新ListView,这将导致异常。

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

您可以在synchronizationCallback中实现自己的锁,如下所示:

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锁。

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();
        }

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

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

1 个答案:

答案 0 :(得分:0)

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