从异步方法返回部分结果

时间:2018-04-10 07:31:53

标签: c# asynchronous async-await task

我有一个调用Web服务的类来异步检索数据。为了提高性能,我实现了一个客户端缓存,它检查所请求的数据是否在本地可用。该类返回存储在缓存中的所有数据,并调用Web服务以获取剩余数据。

我可以将缓存的数据返回给调用者,然后继续进行Web调用,还是必须进行调用并返回完整的数据集?

在同步环境中,我可以使用yield return,使用任务和async / await yield是不可能的。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

您可以使用Observable

 // in your UI
            var result = new ObservableCollection<Data>(); // this is your list to bind to UI

            IsBusy = true; // indicate that work is done
            yourDataSource.GetData(2000).Subscribe(batch =>
            {
                foreach (var d in batch)
                {
                    result.Add(d);
                }
            },
                exception =>
                {
                    Log.Error(exception);
                    IsBusy = false;
                },
                () =>
                {
                    // this means done
                    IsBusy = false;
                }
            )

            // or you can await the whole thing
            try
            {
                IsBusy = true;
                await yourDataSource.GetData(5).Do(batch =>
                {
                    foreach (var d in batch)
                    {
                        result.Add(d);
                    }
                });
            }
            finally
            {
                IsBusy = false;
            }

您的数据来源:

  IObservable<IList<Data>> GetData(int args)
        {
            var result = new Subject<IList<Data>>();

            Task.Run(async () =>
            {
                try
                {
                    var formCache = await GetFromCache(args);

                    result.OnNext(fromCache);

                    while (moreBatches)
                    {
                        result.OnNext(GetNextBatch(args));
                    }

                    result.OnCompleted();
                }
                catch (Exception e)
                {
                    result.OnError(e);
                }
            });

            return result;
        }

如果您使用的是WPF,Xamarin.Forms或UWP,我强烈推荐ReactiveCommand,它可以返回observable并为您完成整个IsBusy。

答案 1 :(得分:0)

这些建议都没有完全符合我的问题,但是它们的组合确实很适合。

首先,我使用TPL DataFlow库创建了一个管道,以从我的源中获取数据。然后,结果会在最后发布到BufferBlock<T>,最终用户将IObservable<T>作为unzip openliberty-18.0.0.1.zip。这有额外的好处,我现在可以通过附加块轻松查询相关数据。