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;