从 C# 中的多个异步函数同时更改列表<T>

问题描述 投票:0回答:1

因此,我有一个用例,我想将列表传递给同时工作的异步函数。每个函数都会将其结果附加到传递的列表中。所以,我怀疑这会导致列表出现并发问题吗?

var errors = new List<Error>();

var awaitedTasks = new List<Task>();
awaitedTasks.Add(funcA(list));
awaitedTasks.Add(funcB(list));
awaitedTasks.Add(funcC(list));
awaitedTasks.Add(funcD(list));

await Task.WhenAll(awaitedTasks);
c# async-await concurrency thread-safety
1个回答
2
投票

答案是,这取决于情况。有一些关于任务调度程序之类的细节,这些细节可能导致您的函数并行更改列表。

通常最好使用功能范例,您希望方法能够返回它们的值,而不是将它们附加到您提供的列表中。然后调用函数可以将它们收集到结果中。

var awaitedTasks = new List<Task>();
awaitedTasks.Add(funcA());
awaitedTasks.Add(funcB());
awaitedTasks.Add(funcC());
awaitedTasks.Add(funcD());

var list = await Task.WhenAll(awaitedTasks);

如果您需要在项目完成时而不是在所有项目完成后报告函数的进度,您可以使用适当的信号量向函数调用添加延续。

var reportingTasks = awaitedTasks.Select(async result => {
    // code that updates `list` in a thread-safe way
    // (or otherwise reports results)
}).ToList();
await Task.WhenAll(reportingTasks);

这样,管理复杂性的代码就全部集中在一个地方,而不是分散在各种异步函数中。

© www.soinside.com 2019 - 2024. All rights reserved.