c# - 异步等待过度使用
问题描述
我有一个关于过度使用async-await
运算符的问题。
我有一个Zoo
实例列表,我需要将每个实例的每个成员分别插入Zoo
到数据库中。这是Zoo
类定义:
class Zoo
{
public Dog Dog { get; set; }
public Cat Cat { get; set; }
public Bear Bear { get; set; }
}
下面提供插入方法Zoo
。每个实例Zoo
及其成员都应该在插入之前进行验证或转换,所以我处理它们Parallel.For
:
public void Save(List<Zoo> zoos)
{
Parallel.For(0, zoos.Count, new ParallelOptions { MaxDegreeOfParallelism = 4 }, async i =>
{
...
Task saveDog = Task.Run(async () => await InsertDogAsync(zoos[i], string connectionString));
Task saveCat = Task.Run(async () => await InsertCatAsync(zoos[i], string connectionString));
Task saveBear = Task.Run(async () => await InsertBearAsync(zoos[i], string connectionString));
await Task.WhenAll(new Task[] { saveDog, saveCat, saveBear });
...
});
}
我使用方法将动物插入数据库async
。例如这里是Dog
:
private static async Task InsertDogAsync(Zoo zoo, string connectionString)
{
using SqlConnection connection = new SqlConnection(connectionString);
await connection.OpenAsync();
...
using SqlCommand insertCommand = new SqlCommand("sp_insertDog", connection); // stored procedure
...
await insertCommand.ExecuteNonQueryAsync();
}
我的问题如下:是否过度使用async-await
运算符?正如我所意识到的,每个await
操作员在完成之前都会释放线程,但是方法是在并行任务中调用的,因此线程用于不同的任务。也许从lambda中删除一些async-await
(例如)更容易接受?Task.Run
解决方案
这不是await
过度使用的情况,而是await
滥用的情况。该Parallel.ForEach
方法不是异步友好的,并且使用async
委托提供给它是一个错误:它没有做你期望它做的事情。如果要同时启动多个异步操作,同时控制并发级别,正确使用的 API 就是Parallel.ForEachAsync
方法。此方法将在即将推出的 .NET 6 中引入,因此目前您只能使用自制解决方案,例如在这个问题中找到的解决方案。
推荐阅读
- javascript - NextJS 动态页面无法爬取
- vue.js - 更新 $vm0 不会立即更新数据
- nativescript - 如何调试 nativescript 抛出“NativeScript 捕获信号 11”。错误?
- c++ - 如何使用不同的参数多次调用函数?
- bash - 如何在centos 7中递归打开文件.txt
- python - For 循环、条件语句、计数
- java - 为什么当我更改静态文件并重新加载页面时 spring devtools 不起作用?
- c# - c#实体框架循环遍历记录savechanges()错误
- django - 来自不同模型的图像字段的 Django GET API
- c# - 为什么是 GetHostEvidence
() 返回 null 而不是预期的 StrongName?