链接任务和返回结果

时间:2018-07-14 15:10:56

标签: c# task-parallel-library ef-core-2.0

我对使用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

1 个答案:

答案 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;
}