Dot-Net
如何將“Where”與非同步謂詞一起使用?
我有一個這樣的非同步謂詞方法:
private async Task<bool> MeetsCriteria(Uri address) { //Do something involving awaiting an HTTP request. }假設我有一個
Uris 集合:var addresses = new[] { new Uri("http://www.google.com/"), new Uri("http://www.stackoverflow.com/") //etc. };我想
addresses使用MeetsCriteria. 我想非同步執行此操作;我希望對謂詞的多次呼叫非同步執行,然後我想等待它們全部完成並生成過濾後的結果集。不幸的是,LINQ 似乎不支持非同步謂詞,所以這樣的事情不起作用:var filteredAddresses = addresses.Where(MeetsCriteria);有沒有類似方便的方法來做到這一點?
我認為框架中沒有這樣的原因之一是存在很多可能的變化,並且在某些情況下每個選擇都是正確的:
謂詞應該並行執行還是串列執行?
如果它們並行執行,是應該全部同時執行,還是應該限制並行度?
如果它們並行執行,結果應該與原始集合的順序相同、完成順序還是未定義順序?
- 如果它們應該按完成的順序返回,是否應該有某種方法(非同步)在它們完成時獲取結果?(這需要將返回類型從更改為
Task<IEnumerable<T>其他類型。)您說您希望謂詞並行執行。在這種情況下,最簡單的選擇是一次執行它們並按完成順序返回它們:
static async Task<IEnumerable<T> Where<T>( this IEnumerable<T> source, Func<T, Task<bool> predicate) { var results = new ConcurrentQueue<T>(); var tasks = source.Select( async x => { if (await predicate(x)) results.Enqueue(x); }); await Task.WhenAll(tasks); return results; }然後你可以像這樣使用它:
var filteredAddresses = await addresses.Where(MeetsCriteria);