.net 等待任务';迷路';使用dbContext.savechanges()
我在Task.Run()/Task.Factory.StartNew()中偶尔会遇到类似的问题,所以我想我对它的用法一定有一些非常基本的不了解(对于那些喜欢花括号的人,我很抱歉不得不在VB中混淆视听): 我有一个异步方法,代码如下:.net 等待任务';迷路';使用dbContext.savechanges(),.net,vb.net,entity-framework,task-parallel-library,.net,Vb.net,Entity Framework,Task Parallel Library,我在Task.Run()/Task.Factory.StartNew()中偶尔会遇到类似的问题,所以我想我对它的用法一定有一些非常基本的不了解(对于那些喜欢花括号的人,我很抱歉不得不在VB中混淆视听): 我有一个异步方法,代码如下: Try Using context As New ECOSSContext context.Meters.Attach(entity) Await Task.Run(Sub() _
Try
Using context As New ECOSSContext
context.Meters.Attach(entity)
Await Task.Run(Sub() _
context.SaveChanges() _
)
'ANY CODE HERE NEVER GETS FIRED
End Using
Return True
Catch ex As Exception
Return False
End Try
它是从以下同步方法调用的:
Dim result = ModelService.MeterResolution.SaveMeter(data).Result
据我所知,这应该等到方法SaveMeter()返回一个结果。我前面列出的异步方法应该等待Task.Run行,直到它返回,然后继续(因此是wait)。相反,一旦到达等待行,调用堆栈似乎就会退出。SaveChanges()成功,但我无法将此事实通知客户端
我在不同的应用程序中相对频繁地使用TPL,并且没有这些问题,但是我需要使用context.SaveChanges()之类的方法
如有任何建议,我们将不胜感激。我希望我没有误读文档。问题实际上是由于您使用了
结果。从同步代码调用async
代码可能非常棘手
我解释这个问题。简言之,默认情况下,在每个wait
的开头都会保存一个“上下文”,用于恢复该方法
因此,如果在UI或ASP.NET上下文中调用此函数,当await
完成时,async
方法将尝试重新进入该上下文以继续执行。不幸的是,使用Result
(或Wait
)的代码将阻塞该上下文中的线程,因此async
方法无法完成
避免这种情况的准则是:
尽可能多地使用ConfigureAwait(continueOnCapturedContext:false)
。这使您的async
方法能够继续执行,而无需重新输入上下文
始终使用async
。使用Wait
代替Result
或Wait
除非这是EF6版本之一,否则在多个线程上使用DbContext
通常不是一个好主意。您可能想做的是将整个函数移动到一个异步方法中,确保在单个线程上创建、使用和销毁DbContext
。@CodingGorilla--谢谢您的提示。这一特定指南的理由/权威是什么?请参阅此常见问题解答:@CodingGorilla——谢谢。这不适用,因为我在一个高度分布式的系统中,因此我为每个操作打开和关闭一个上下文。有趣的是——我会深入研究一下你的博客,然后再回复你。你的博客写得非常好。谢谢你的帮助,我很抱歉问了这么多问题!