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()メソッドが結果を返すまで待つ必要があります。そして、前にレイアウトしたasyncメソッドは、Task.Run行が戻るまで待機してから、続行する必要があります(したがって待機します)。代わりに、Awaitラインに到達するとすぐに、コールスタックが終了したように見えます。SaveChanges()は成功しますが、この事実をクライアントに通知できません。

別のアプリケーションでTPLを比較的頻繁に使用しており、これらの問題は発生していませんが、context.SaveChanges()のようなメソッドを使用する必要はありません。

任意の提案をいただければ幸いです。ドキュメントを読み間違えただけではないことを願っています。

4

1 に答える 1

3

問題は、実際にはの使用によるものですResultasync同期コードからコードを呼び出すのは非常に難しい場合があります。

このデッドロックの完全な理由をブログで説明します。つまり、それぞれの先頭にデフォルトで保存されawait、メソッドを再開するために使用される「コンテキスト」があります。

したがって、これがUIまたはASP.NETコンテキストで呼び出された場合、await完了時に、asyncメソッドはそのコンテキストに再入力して実行を続行しようとします。Result残念ながら、 (または)を使用するコードWaitはそのコンテキストでスレッドをブロックするため、asyncメソッドを完了できません。

これを回避するためのガイドラインは次のとおりです。

  1. ConfigureAwait(continueOnCapturedContext: false)可能な限り使用してください。これによりasync、コンテキストを再入力しなくても、メソッドの実行を継続できます。
  2. asyncずっと使ってください。またはawaitの代わりに使用します。ResultWait
于 2013-01-23T02:44:54.333 に答える