微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

异步等待过度使用

如何解决异步等待过度使用

我有一个关于过度使用 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 运算符在完成之前都会释放线程,但方法是在并行任务中调用的,因此线程用于不同的任务。也许从 async-await lambda 中移除一些 Task.Run 更容易接受?

解决方法

这不是 await 过度使用的情况,而是 await 滥用的情况。 Parallel.ForEach 方法 is not async-friendly 和一个 async 委托是一个错误:它没有做你期望它做的事情。如果要同时启动多个异步操作,同时控制并发级别,则正确使用的 API 是 Parallel.ForEachAsync 方法。此方法将在即将推出的 .NET 6 中引入,因此目前您只能使用自制解决方案,例如在 this 问题中找到的解决方案。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。