如何在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那么这可能会大大减少冗长。