并行或异步 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上,效果是一样的
- 否则,当工作在其他地方完成时,您将只使用一个线程
我在谷歌上搜索了很多,但恐怕我不完全理解并发和并行的后果。
我有大约 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上,效果是一样的 - 否则,当工作在其他地方完成时,您将只使用一个线程