2017-04-13 22 views
3

這裏是設置:有一個聯邦遠程服務返回一個特定的值是否正確或不正確。我們可以根據需要發送請求,最多可以向遠程服務發送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內的任何響應代碼表示該值是「正確的」)。

有沒有辦法讓這段代碼更聰明一點,所以我們儘量減少請求的數量?不幸的是,我們正在驗證的價值是均勻分佈的,所以對請求進行排序不會產生任何效果(我知道這一點)。

+3

Observable是否有'WhenAny'實現? – stuartd

+0

使用System.Reactive,我不確定。我沒有看到可用於該代碼的方法。 – djbyter

回答

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); 
+0

FirstAsync似乎沒有讓我檢查條件,看看我是否有結果。 – djbyter

+0

@djbyter'FirstAsync'類似於'LINQ'中的'First',你是否嘗試過濾你的事件? – VMAtm

+0

這個伎倆。運作良好,我只是不知道FirstAsync能夠接受條件。 – djbyter

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(); 

這樣,您的可觀察值將繼續發出值,因此您可以繼續對其執行操作。

+0

這似乎更好,因爲我儘快得到結果,但它確實繼續運行所有請求。 – djbyter

相關問題