BindingOperations.EnableCollectionSynchronization 和 CollectionChanged 在多线程 WPF 应用程序中的交互
Interaction of BindingOperations.EnableCollectionSynchronization and CollectionChanged in multi threaded WPF application
我正在尝试开发多线程 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
只会更新为以后的状态。
是的,这是一个问题 - 您可能会收到“在 OnCollectionChanged 事件期间无法更改集合”异常,因为在第二个工作线程尝试之前事件可能尚未完成改变集合的状态。
我正在尝试开发多线程 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
只会更新为以后的状态。
是的,这是一个问题 - 您可能会收到“在 OnCollectionChanged 事件期间无法更改集合”异常,因为在第二个工作线程尝试之前事件可能尚未完成改变集合的状态。