ReactiveExtension 按需调用异步代码

ReactiveExtension calling async code on demand

我有一个 属性 IObservable<ServiceStatus> 应该通过使用异步模式的方法按需更新。如果发生任何错误,则应将其吞下。 statusNeedToBeUpdated 是一个通知我的 observable,当我的 属性 应该更新时。基本上下面的代码完成了需要做的事情:

Status = statusNeedToBeUpdated
    .Select(_ => {
        try {
            var task = client.ServiceStatus.GetAsync();
            task.Wait();
            return task.Result;
        }
        catch (Exception) {
            return null;
        }
    })
    .Where(status => status != null);

我认为应该有更高级的方法来处理对 client.ServiceStatus 的异步调用:我想到了这个:

Status = statusNeedToBeUpdated
    .Select(async _ => await client.ServiceStatus.GetAsync())
    .Catch(Observable.Return(Task.Factory.StartNew(()=> (ServiceStatus)null)))
    .Where(task => task.Result != null)
    .Select(task => task.Result);

这个解决方案更好,但我不喜欢启动一个简单 returns null 的新任务。 有没有人知道更好的解决方案。

您可以使用 Task<ServiceStatus>.FromResult(null) 这将 return 一个已经完成的任务,而不是创建一个新任务。

但您也可以使用 Observable.FromAsync 来简化它。

Status = statusNeedToBeUpdated
   .Select(_ => Observable.FromAsync<ServiceStatus>(async () => await client.ServiceStatus.GetAsync())
   .SelectMany(s=> s);

在我看来你需要这个查询:

Status =
    statusNeedToBeUpdated
        .SelectMany(_ =>
            Observable
                .FromAsync(() => client.ServiceStatus.GetAsync())
                .Retry());

这将在任何时候重试 GetAsync 抛出错误并避免需要 return 虚拟值或任务。