并行或异步 ASP.NET 核心 C#

Parallel or async ASP.NET Core C#

我在谷歌上搜索了很多,但恐怕我不完全理解并发和并行的后果。

我有大约 3000 行数据库对象,每个对象平均附加了 2-4 个逻辑数据,需要作为搜索查询的一部分进行验证,这意味着验证服务需要执行大约。 3*3000次。例如。用户已按颜色过滤,然后每一行都需要验证颜色和 return 结果。找到匹配时循环不会中断,这意味着将始终需要评估所有逻辑对象(这是由于相关性的计算而不是匹配)。

这是在用户选择各种属性时按需完成的,这意味着性能是这里的关键。

我目前正在使用 Parallel.ForEach 来执行此操作,但想知道使用异步行为是否更聪明?

当前方式

var validatorService = new LogicalGroupValidatorService();
ConcurrentBag<StandardSearchResult> results = new ConcurrentBag<StandardSearchResult>();
Parallel.ForEach(searchGroups, (group) =>
{
    var searchGroupResult = validatorService.ValidateLogicGroupRecursivly(
        propertySearchQuery, group.StandardPropertyLogicalGroup);
    result.Add(new StandardSearchResult(searchGroupResult));
});

异步示例代码

var validatorService = new LogicalGroupValidatorService();
List<StandardSearchResult> results = new List<StandardSearchResult>();
var tasks = new List<Task<StandardPropertyLogicalGroupSearchResult>>();

foreach (var group in searchGroups)
{
    tasks.Add(validatorService.ValidateLogicGroupRecursivlyAsync(
        propertySearchQuery, group.StandardPropertyLogicalGroup));
}

await Task.WhenAll(tasks);

results = tasks.Select(logicalGroupResultTask => 
    new StandardSearchResult(logicalGroupResultTask.Result)).ToList();

并行和异步的区别是:

  • 并行:启动多个线程并将工作分配给每个线程
  • 异步:以 non-blocking 方式完成工作。

这是否会产生影响取决于 async-way 中阻塞的是什么。如果您正在 CPU 上工作,那么阻塞您的是 CPU,因此您最终仍会遇到多个线程。如果它是 IO(或除 CPU 之外的任何其他内容,您将重用相同的线程)

对于您的特定示例,这意味着以下内容:

Parallel.ForEach => 为列表中的每个项目启动新线程(启动的线程数由 CLR 管理)并在不同的线程上执行每个项目

async/await => 做这部分工作,但让我继续执行。因为你有很多项目,这意味着多次说这个。现在就看结果如何了:

  • 如果this bit of work放在CPU上,效果是一样的
  • 否则,当工作在其他地方完成时,您将只使用一个线程