我已经把一个线程安全的ObservableCollection放在一起用于WPF,但遇到了非常偶然的锁定问题。
锁定机制是ReaderWriterLockSlim
。为了减轻集合本身的代码,我实现了一个IDisposable帮助器:
private class WriteLocker : IDisposable
{
ThreadSafeObservableCollection<T> _Target;
bool _HasLock = false;
public WriteLocker(ThreadSafeObservableCollection<T> target)
{
_Target = target;
try { }
finally
{
_Target._Sync.EnterWriteLock();
_HasLock = true;
}
}
public void Dispose()
{
if (_HasLock)
{
try { }
finally
{
_Target._Sync.ExitWriteLock();
}
}
}
}
使用相同的ReadLocker。
然后我可以这样在集合中使用它:
new public void Add(T item)
{
using (WriteLock())
{
base.Add(item);
}
}
由于以下原因,我的通知不会打扰调度员:
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (_Paused) return;
NotifyCollectionChangedEventHandler eventHandler = CollectionChanged;
if (eventHandler == null)
return;
Delegate[] delegates = eventHandler.GetInvocationList();
foreach (NotifyCollectionChangedEventHandler handler in delegates)
{
DispatcherObject dispatcherObject = handler.Target as DispatcherObject;
if (dispatcherObject != null && dispatcherObject.CheckAccess() == false)
{
dispatcherObject.Dispatcher.Invoke(DispatcherPriority.DataBind, handler, this, e);
}
else
{
handler(this, e);
}
}
}
现在有时我最终会锁定_Target._Sync.EnterWriteLock()
。在调试器中,我可以观察ReaderWriterLockSlim的状态:
It has a writeLockOwnerId, but writeLockHeld is false
我的问题是......这怎么可能发生?我的印象是,我无法做任何事情,无法解锁我的锁定从use(){}块。我也很好奇什么情况会以这种方式破坏锁定 - 或者这是正常情况吗?
编辑:
WriteLock()的代码就是:
protected IDisposable WriteLock()
{
return new WriteLocker(this);
}
以下是完整的代码:ThreadSafeObservableCollection.cs