1

Task.Run()/Task.Factory.StartNew() 偶尔会遇到类似的问题,所以我认为必须有一些非常基本的东西,我不了解它的使用(对于那些喜欢花括号的人) ,我很抱歉不得不混淆VB):

我有一个带有以下代码的异步方法:

       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 行上等待,直到它返回,然后继续(因此等待)。相反,一旦命中 Await 行,调用堆栈似乎就退出了。SaveChanges() 成功,但我无法告知客户这一事实。

我在不同的应用程序中相对频繁地使用 TPL 并且没有遇到这些问题,但是没有我需要使用的 context.SaveChanges() 之类的方法。

任何建议表示赞赏。我希望我不只是误读了文档。

4

1 回答 1

3

问题实际上是由于您使用Result. 从同步代码调用async代码可能非常棘手。

我在我的博客上解释了这个僵局的全部原因。简而言之,有一个“上下文”默认保存在每个开头await并用于恢复该方法。

因此,如果在 UI 或 ASP.NET 上下文中调用此方法,则在await完成时,该async方法会尝试重新进入该上下文以继续执行。不幸的是,使用Result(or Wait) 的代码将阻塞该上下文中的线程,因此该async方法无法完成。

避免这种情况的准则是:

  1. ConfigureAwait(continueOnCapturedContext: false)尽可能多地使用。这使您的async方法能够继续执行而无需重新进入上下文。
  2. async一路使用。使用await代替Resultor Wait
于 2013-01-23T02:44:54.333 回答