如何在addrange select语句中添加异步“await”?
我有这样的function:
public async Task SampleFunction() { var data = service.GetData(); var myList = new List(); myList.AddRange(data.select(x => new SomeViewModel { Id = x.Id, DateCreated = x.DateCreated, Data = await service.GetSomeDataById(x.Id) } return myList; }
我的await
不起作用,因为它只能用于标记有async
修饰符的方法或lambda。 我在哪里放置async
与此function?
您只能在async
方法/委托中使用await
。 在这种情况下,您必须将该lambda表达式标记为async
。
但等等,还有更多……
Select
是来自async
前时代,所以它不处理async
lambdas(在你的情况下,它将返回IEnumerable
而不是IEnumerable
这是你真正需要的)。
但是,您可以自己添加该function(最好是作为扩展方法),但是您需要考虑是否要await
每个项目,然后再转到下一个(顺序)或在结束时同时await
所有项目(同时)。
顺序async
static async Task SelectAsync(this IEnumerable enumerable, Func> selector) { var results = new List (); foreach (var item in enumerable) { results.Add(await selector(item)); } return results.ToArray(); }
并发async
static Task SelectAsync(this IEnumerable enumerable, Func> selector) { return Task.WhenAll(enumerable.Select(selector)); }
用法
public Task SampleFunction() { return service.GetData().SelectAsync(async x => new SomeViewModel { Id = x.Id, DateCreated = x.DateCreated, Data = await service.GetSomeDataById(x.Id) } }
你在lambda中使用await
,而lambda将由编译器转换为它自己独立的命名方法。 要使用await
它本身必须是async
,而不仅仅是在async
方法中定义。 当你使lambda async
你现在有一系列任务,你想要异步地转换成它们的结果序列。 Task.WhenAll
正是这样做的,所以我们可以将新查询传递给WhenAll
来获取表示结果的任务,这正是此方法想要返回的内容:
public Task SampleFunction() { return Task.WhenAll(service.GetData().Select( async x => new SomeViewModel { Id = x.Id, DateCreated = x.DateCreated, Data = await service.GetSomeDataById(x.Id) })); }
虽然对于您的用例来说可能过重,但使用TPL Dataflow可以更好地控制异步处理。
public async Task> SampleFunction() { var data = service.GetData(); var transformBlock = new TransformBlock( async x => new SomeViewModel { Id = x.Id, DateCreated = x.DateCreated, Data = await service.GetSomeDataById(x.Id) }, new ExecutionDataflowBlockOptions { // Let 8 "service.GetSomeDataById" calls run at once. MaxDegreeOfParallelism = 8 }); var result = new List(); var actionBlock = new ActionBlock ( vm => result.Add(vm)); transformBlock.LinkTo(actionBlock, new DataflowLinkOptions { PropagateCompletion = true }); foreach (var x in data) { transformBlock.Post(x); } transformBlock.Complete(); await actionBlock.Completion; return result; }
如果service.GetData()
返回一个IObservable
并且此方法返回了一个IObservable
那么这可能会大大减少冗长。