【发布时间】:2023-03-16 00:34:01
【问题描述】:
我无法正确构建最有效的方法来迭代从请求对象启动的多个异步任务,然后执行一些其他异步任务,这些任务同时依赖于请求对象和第一个异步任务的结果。我在 AWS 中运行 C# lambda 函数。我已经尝试过这样的模型(为简洁起见,省略了错误处理等):
public async Task MyAsyncWrapper()
{
List<Task> Tasks = new List<Task>();
foreach (var Request in Requests)
{
var Continuation = this.ExecuteAsync(Request).ContinueWith(async x => {
var KeyValuePair<bool, string> Result = x.Result;
if (Result.Key == true)
{
await this.DoSomethingElseAsync(Request.Id, Request.Name, Result.Value);
Console.WriteLine("COMPLETED");
}
}
Tasks.Add(Continuation);
}
Task.WaitAll(Tasks.ToArray());
}
这种方法导致 DoSomethingElseAsync() 方法并没有真正得到等待,并且在我的许多 Lambda 函数调用中,我从未得到“COMPLETED”输出。我也用这种方法解决了这个问题:
public async Task MyAsyncWrapper()
{
foreach (var Request in Requests)
{
KeyValuePair<bool, string> Result = await this.ExecuteAsync(Request);
if (Result.Key == true)
{
await this.DoSomethingElseAsync(Request.Id, Request.Name, Result.Value);
Console.WriteLine("COMPLETED");
}
}
}
这可行,但我认为这很浪费,因为我只能在等待 asnyc 完成时执行循环的一次迭代。我也引用了Interleaved Tasks,但问题是我基本上有两个循环,一个用于填充任务,另一个用于在它们完成后对其进行迭代,我无法再访问原始的Request 对象.所以基本上是这样的:
List<Task<KeyValuePair<bool, string>>> Tasks = new List<Task<KeyValuePair<bool, string>>>();
foreach (var Request in Requests)
{
Tasks.Add(ths.ExecuteAsync(Request);
}
foreach (Task<KeyValuePair<bool, string>> ResultTask in Tasks.Interleaved())
{
KeyValuePair<bool, string> Result = ResultTask.Result;
//Can't access the original request for this method's parameters
await this.DoSomethingElseAsync(???, ???, Result.Value);
}
对于在 foreach 循环中实现这种类型的异步链接的更好方法有什么想法吗?我的理想方法不是将请求对象作为来自ExecuteAsync() 的响应的一部分返回,所以如果可能的话,我想尝试寻找其他选项。
【问题讨论】:
标签: c# asynchronous async-await parallel-foreach