我测试了两段代码:
FYI ldocs是IEnumerable<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的每一端。我这么想对吗?
发布于 2022-05-02 15:18:14
为了简化,您需要了解以下内容之间的区别:
await Task.WhenAll(something.Select(async () => await DoSomethingAsync()).ToArray());这是:
await Task.WhenAll(something.Select(() => DoSomethingAsync()).ToArray());对我来说,正确的代码是第二个,因为在第一个代码中,它在等待api的每个端?
不,你误解了它的工作方式。DoSomethingAsync()仍将被并发调用,并且生成的任务仍将同时完成。添加的异步/等待的唯一区别是编译器将一些状态机代码添加到lambda函数中,这样如果抛出异常,lambda将出现在堆栈跟踪中。
与您正在使用的任何异步操作相比,来自附加状态机代码的性能差异可以忽略不计。
让堆栈跟踪显示异步方法调用发生的位置通常是有价值的。在这种情况下,这可能不是什么大不了的事,因为await Task.WhenAll()离方法调用只有一行之遥,所以对于如何调用DoSomethingAsync并没有什么含糊之处。但是,您可以想象从不同的代码部分调用DoSomethingAsync的场景,并以完全不同的方法等待产生的任务:如果堆栈跟踪中没有包含该代码行,那么可能很难找到导致抛出异常的路径。
https://stackoverflow.com/questions/72088547
复制相似问题