以下是设置:有一个联邦远程服务可以返回特定值是正确还是不正确。我们可以根据需要发送请求,每个请求最多可以发送50个远程服务。
由于我们只需要使用正确的值,并且可能值的集合很小(~700),我们只能发送15个左右的50个批处理请求,正确的值将成为结果集的一部分。因此,我使用了以下代码:
Observable
.Range(0, requests.Count)
.Select(i => Observable.FromAsync(async () =>
{
responses.Add(await client.FederalService.VerifyAsync(requests[i]));
Console.Write(".");
}))
.Merge(8)
.Wait();
但是 - 我不喜欢的是,如果之前的一个请求具有正确的值,我仍然会通过服务浪费时间运行所有可能性。我试图让这次运行尽可能快。我知道退出条件(响应代码从1到99,50-59内的任何响应代码表示该值是“正确的”)。
有没有办法让这段代码更聪明,所以我们最小化请求数量?不幸的是,我们验证的值是均匀分布的,因此排序请求什么都不做(我知道)。
答案 0 :(得分:3)
您应该考虑使用FirstAsync
method here:
我们示例中的秘密是
FirstAsync
方法。我们实际上在等待观察者返回的第一个结果,不关心任何进一步的结果。
所以你的代码可能是这样的:
await Observable
.Range(0, requests.Count)
.Select(i => Observable.FromAsync(async () =>
{
responses.Add(await client.FederalService.VerifyAsync(requests[i]));
Console.Write(".");
}))
.FirstAsync()
.Subscribe(Console.WriteLine);
> System.Reactive.Linq.ObservableImpl.Defer`1[System.Reactive.Unit]
Rx and Await: Some Notes文章提供了类似方法的一些技巧。例如,您有FirstAsync
的重载,可以过滤,LINQ
'方法First
:
await Observable
.Range(0, requests.Count)
.Select(i => Observable.FromAsync(async () =>
{
responses.Add(await client.FederalService.VerifyAsync(requests[i]));
Console.Write(".");
}))
.FirstAsync(r => /* do the check here */)
.Subscribe(Console.WriteLine);
答案 1 :(得分:1)
你非常接近。将您的观察结果更改为:
Observable
.Range(0, requests.Count)
.Select(i => Observable.FromAsync(async () =>
{
var response = await Task.FromResult(i); //replace with client.FederalService.VerifyAsync(requests[i])
responses.Add(response);
Console.Write($"{i}.");
var responseCode = response; //replace with however you get the response code.
return responseCode >= 50 && responseCode <= 59;
}))
.Merge(8)
.Where(b => b)
.Take(1)
.Wait();
这样你的observable继续发出值,所以你可以继续对它进行操作。