c# - 并行处理三个数据库操作
问题描述
我仍在加快异步/等待的速度,我主要将此作为一个学习问题提出。
我有这个方法可以简单地连续创建三个对象。
问题是,这些实际上是并行处理的吗?意思是多线程?
还是每个人实际上都在等待最后一个完成后再开始?
private async Task AddDefaultTasks(Item project)
{
await this.AddChildAsync(project, "Task A", Enums.ItemTypes.Task);
await this.AddChildAsync(project, "Task B", Enums.ItemTypes.Task);
await this.AddChildAsync(project, "Task C", Enums.ItemTypes.Task);
}
private async Task<Item> AddChildAsync(Item parent, string name, Enums.ItemTypes itemType)
{
return await this.NewAsync(new Item() { Name = name, ParentId = parent.Id, ItemTypeId = (int)itemType });
}
public async Task<Item> NewAsync(Item item)
{
item.OwnedById = this._applicationUserProvider.CurrentAppUserId;
item.InsertedBy = item.OwnedById;
item.UpdatedBy = item.InsertedBy;
item.EntityStatusId = (int)Enums.EntityStatus.Active;
DbContext.Items.Add(item);
await this.SaveChangesAsync();
return item;
}
有没有更有效的方法来编写异步/等待,比如等待所有?(除了创建所有三个并保存一次的明显方式)。据我了解,EntityFrameworkCore 不支持并行,在这种情况下,我为每个 HttpRequest 使用单个上下文。
解决方案
让我们从基础开始,然后转到特定于 EF 的代码。
问题是,这些实际上是并行处理的吗?意思是多线程?
不,并行和异步处理不一样。没有什么可以让前面的代码并行运行,实际上都是顺序的。
不,
async
andawait
关键字不创建也不与Thread
s 一起使用。
作为附加说明,您可以从 中删除async
和await
关键字AddChildAsync
,它们不是必需的。
如果您想以并行、异步的方式运行代码,您可以:
await Task.WhenAll(
this.AddChildAsync(project, "Task A", Enums.ItemTypes.Task),
this.AddChildAsync(project, "Task B", Enums.ItemTypes.Task)
this.AddChildAsync(project, "Task C", Enums.ItemTypes.Task)
);
这将并行启动和运行所有三个任务。
但是,DbContext
操作不是线程安全的,上面的代码很可能会严重失败。
有两种方法可以解决这个问题:
- 让
AddChildAsync
spawn 成为自己的DbContext
. 这将允许您使用我之前提到的并行代码。 - 制作另一个
AddChildAsync
不保存更改的内容,或者使用布尔值来确定是否保存。有了这个,你只会在所有三个实体都添加到上下文之后调用数据库。这虽然是顺序的,但很容易比上述代码的并行处理更快。
推荐阅读
- python - Python 3.6 安装失败
- react-redux - 减速器和全局变量是否相同?
- python - 复杂的熊猫子设置;在多列中选择符合条件的行
- c++ - 为自定义迭代器专门化 std::copy
- mysql - R:如何从 MySQL 中正确获取特殊字符?
- anaconda - 查询 anaconda 包的目标平台
- powershell - 如何使用powershell将键/输入发送到没有登录用户的正在运行的进程?
- java - 从 URL 下载文件?
- node.js - 理解 fs.writeFileSync(path, data[, options]) Node.js
- python - 将 args 作为单元测试的一部分传递以测试 pyspark 脚本