我对使用TPL链接任务有疑问。它必须与Entity Framework Core一起使用,因此我们不支持在同一数据库上下文上进行并发操作。
我想尽可能地异步。以下是没有异步的代码:
ExecStartPre=/bin/sleep 30
我现在要使方法Context.Set<T>().Add(entity);
Context.SaveChanges();
return entity;
,AddAsync
链接起来,使它异步。我必须确保在致电SaveChangesAsync
之前完成AddAsync
。
我的第一次尝试是:
SaveChangesAsync
但是我不认为这是正确的。 public Task<T> AddAsync(T entity)
{
return _dbContext.Set<T>()
.AddAsync(entity)
.ContinueWith(addTask =>
{
_dbContext.SaveChangesAsync();
return addTask.Result.Entity;
});
}
未包含在返回的任务中。如果我拨打:SaveChangesAsync()
,是否确定await AddAsync(myEntity);
将完成?我不这么认为。
因此,我试图解决此问题,但最终遇到了嵌套的任务,这些任务不是非常用户友好。可能的解决方案是这样的(伪代码,无法编译):
SaveChangesAsync()
是否有使用TPL实现此行为的方法?如果是,我是否只是重写return Context.Set<T>()
.AddAsync(entity)
.ContinueWith(addTask =>
{
return Context.SaveChangesAsync()
.ContinueWith(saveTask =>
{
return addTask.GetAwaiter().GetResult().Entity;
});
});
?这是许多项目应使用的API。我想使该API尽可能具有高性能(至少在理论上是这样。我正在使用它来学习)。用户应在API之外使用await
。我要避免的事情是通过等待在API内部产生瓶颈。我不确定await
是否只是ContinueWith
的其他实现。使用await
代替ContinueWith
时要避免的另一件事是将方法标记为await
。
答案 0 :(得分:1)
我不确定AddAsync
为什么是Entity Framework Core的一部分,因为它仅应将项目添加到变更跟踪器(内存中),因此它不执行任何实际的异步操作。
我要说的是,您不应该依赖它,因为有些驱动程序(例如MySQL官方)在调用AddAsync
时会死锁。
如果要使用实际的异步实现,只需使用:
public async Task<T> AddAsync(T entity)
{
_dbContext.Set<T>().Add(entity);
await _dbContext.SaveChangesAsync();
return entity;
}