entity framework6.1.0 SaveChangesAsync

我有EF助手类保存更改异步:

public async Task SaveOrUpdateAsync(TEntity entity) where TEntity : class, IContextEntity { if (entity.Id == 0) context.Set().Add(entity); else { TEntity dbEntry = context.Set().Find(entity.Id); if (dbEntry != null) dbEntry = entity; } return await context.SaveChangesAsync(); } public void Save() { Task saveEntit1Async = repository.SaveOrUpdateAsync(entity1); Task saveEntity2Async = repository.SaveOrUpdateAsync(entity2); Task saveEntity3Async = repository.SaveOrUpdateAsync(Entity3); Task.WaitAll(saveEntit1Async, saveEntity2Async, saveEntity3Async); string test = "test"; ) 

电话被卡住了

 Task.WaitAll(saveEntit1Async, saveEntity2Async, saveEntity3Async); 

线,永远不会到达

  string test = "test"; 

但如果我运行它:

 public void Save() { repository.SaveOrUpdateAsync(entity1); repository.SaveOrUpdateAsync(entity2); repository.SaveOrUpdateAsync(Entity3); string test = "test"; ) 

它运行正常,所有更改都被保存并且可以实现

 string test = "test"; 

为什么是

 Task.WaitAll(saveEntit1Async, saveEntity2Async, saveEntity3Async); 

冻结操作并且永远不会将调用传递给下一行代码(string test =“test”;)?

我想到了!

这是发生的问题,当您使用“等待”方法等待任务或直接从任务的“结果”属性获取结果时,您同时阻止主线程。 当最终任务在线程池中的该方法(SaveOrUpdateAsync(TEntity entity))内完成时,它将调用continuation以回发到主线程(因为它从未离开它),因为SynchronizationContext.Current可用并被捕获。 但是这里有一个问题:主线程被“等待”方法阻止,这就是我陷入僵局的方式!

为了修复死锁问题,我必须指定不继续捕获context.SaveChangesAsync()的上下文。

 public async Task SaveOrUpdateAsync(TEntity entity) where TEntity : class, IContextEntity { if (entity.Id == 0) context.Set().Add(entity); else { TEntity dbEntry = context.Set().Find(entity.Id); if (dbEntry != null) dbEntry = entity; } return await context.SaveChangesAsync().ConfigureAwait(continueOnCapturedContext: false); } 

也许我是愚蠢的(!),但为什么你的代码说

 if (dbEntry != null) dbEntry = entity; 

当然,如果声明应该是

 if (dbEntry == null) dbEntry = entity; 

我猜C#null-coalescing运算符也可以替换这两行

 TEntity dbEntry = context.Set().Find(entity.Id) ?? entity;