性能 LINQ 异步等待

Performance LINQ async await

我测试了2段代码:

仅供参考 ldocsIEnumerable<BsonDocument> 并且 doAmethodAsync 调用 API。

var tasks = new List<(BsonDocument docs, int status, bool isSuccess)>>();
tasks.AddRange(ldocs.Select(async b => await doAmethodAsync())
result = await Task.WhenAll(tasks.toArray()).configuration(false)
tasks.RemoveAll(task => task.IsCompleted);

和另一个一样,只有一个变化:

tasks.AddRange(ldocs.Select(b => doAmethodAsync())

我认为 900 次循环(6-8 秒)的性能差异不大。

对我来说正确的代码是第二个,因为在第一个中它等待 API 的每一端。我这样想对吗?

为简化起见,您问的是这两者之间的区别:

await Task.WhenAll(something.Select(async () => await DoSomethingAsync()).ToArray());

还有这个:

await Task.WhenAll(something.Select(() => DoSomethingAsync()).ToArray());

for me the correct code is the second because in the first its waiting each end of api?

不,您误解了它的工作方式。 DoSomethingAsync() 仍将被并发调用,结果任务仍将并发完成。添加的 async/await 的唯一区别是编译器将一些状态机代码添加到 lambda 函数中,这样如果抛出异常,该 lambda 将出现在您的堆栈跟踪中。

与您正在使用的任何异步操作相比,来自该额外状态机代码的性能差异可以忽略不计。

让堆栈跟踪显示异步方法调用发生的位置通常很有价值。在这种情况下,这可能没什么大不了的,因为 await Task.WhenAll() 距离方法调用仅一行,所以 DoSomethingAsync 的调用方式没有歧义。但是您可以想象从代码的不同部分调用 DoSomethingAsync 的场景,并且结果任务以完全不同的方法等待:可能很难弄清楚是什么路径导致了抛出异常的点如果该行代码未包含在堆栈跟踪中。