如何在同步调用中集成异步调用

时间:2016-07-08 09:59:40

标签: c# asynchronous async-await

我有一个抽象基类,它对来自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);
            //...
        }
    }

0 个答案:

没有答案