我有一个调用Web服务的类来异步检索数据。为了提高性能,我实现了一个客户端缓存,它检查所请求的数据是否在本地可用。该类返回存储在缓存中的所有数据,并调用Web服务以获取剩余数据。
我可以将缓存的数据返回给调用者,然后继续进行Web调用,还是必须进行调用并返回完整的数据集?
在同步环境中,我可以使用yield return
,使用任务和async / await yield是不可能的。
我该如何解决这个问题?
答案 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
。这有额外的好处,我现在可以通过附加块轻松查询相关数据。