我有一个抽象基类,它对来自CollectionChanged
实现实例的INotifyCollectionChanged
事件作出反应。这个抽象类声明了一个抽象方法,派生类必须覆盖并填充其功能。
但是,这些抽象方法是Task方法(异步),所以我需要等待它们。但是我无法在锁定语句中等待,所以我试图在OnSourceCollectionChanged
的调用者中执行锁定...但这不能解决问题。
OnSourceCollectionChanged
是否会产生有/无lock
的竞争条件?
这个问题有解决方案吗?也许有一种更简单的方法 Rx ?
以下是我的示例实现:
public abstract class AbstractCollectionReplicator<TS, TD>
{
private readonly object locker = new object();
protected AbstractCollectionReplicator(INotifyCollectionChanged sourceCollection)
{
sourceCollection.CollectionChanged += (sender, args) =>
{
// ensures the async operation is finished before entering the next
lock (this.locker)
{
this.OnSourceCollectionChanged(sender, args);
}
};
}
protected virtual async void OnSourceCollectionChanged(
object sender,
NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
await this.OnSourceAdd(e.NewItems.OfType<TS>(),
e.NewStartingIndex);
break;
case NotifyCollectionChangedAction.Remove:
await this.OnSourceRemove(e.OldItems.OfType<TS>(),
e.OldStartingIndex);
break;
case NotifyCollectionChangedAction.Replace:
await this.OnSourceReplace(e.OldItems.OfType<TS>(),
e.NewItems.OfType<TS>(),
e.NewStartingIndex);
break;
case NotifyCollectionChangedAction.Move:
await this.OnSourceMove(e.NewItems.OfType<TS>(),
e.OldStartingIndex,
e.NewStartingIndex);
break;
case NotifyCollectionChangedAction.Reset:
break;
}
}
protected abstract Task OnSourceAdd<TS>(IEnumerable<TS> items,
int index);
protected abstract Task OnSourceRemove<TS>(IEnumerable<TS> items,
int index);
protected abstract Task OnSourceReplace<TS>(IEnumerable<TS> items,
IEnumerable<TS> enumerable,
int index);
protected abstract Task OnSourceMove<TS>(IEnumerable<TS> items,
int fromIndex,
int toIndex);
protected abstract Task OnSourceReset();
}
我想在派生类中执行类似的操作:
protected override async Task OnSourceAdd<TS>(IEnumerable<TS> items,
int index)
{
foreach (var item in items)
{
var destinationItem = await this.someAsyncFunc(item);
//...
}
}