2017-10-25 11 views
3

フォワード警告(予想外の)MS-SQL-Serverのをターゲットにする場合、デッドロックをスニペット待つ(予想通り)が、Oracleをターゲットにすると、デッドロックされていません。非同期/

は私が.Resultの使用することを十分に承知しています以下に示す文脈は間違っていますので、絶対に避けてください。私は正しいアプローチが何であるか知っています。

この質問の性質は、db-driversのインフラストラクチャ(Oracle対Ms-Sql-Server)と関連があります。それは大部分の学問的な質問です。


System.Web.MVC.dll: ver. 5.2.3.0 (MVC5) 
EntityFramework.dll: ver. 6.1.3 
EntityFramework.SqlServer.dll: ver. 6.1.3 
Oracle.ManagedDataAccess: ver. 4.121.2.0 (oracle driver ver 12.2.0.1.0) 
Oracle.ManagedDataAccess.EntityFramework: ver. 6.121.2.0 (oracle driver ver 12.2.0.1.0) 

ASP.NET MVCコントローラ内の次のリポジトリとその呼び出しを検討:

public class MyRepository { 
    [...] 
    public async Task<SomeEntity> GetFirstFooAsync() => await new SomeEFContext().FooTable.FirstOrDefaultAsync(); 
} 

public class SomeController : Controller { 
    public ActionResult SomeAction() { 
      var result = new MyRepository.GetFirstFooAsync().Result; //<-- crappy approach I know 
      [...] 
    } 
} 

基礎となるDBは、Oracleである場合、コードの上記部分がデッドロックしません。しかし、EFのためにMSによって提供された関連ドライバーを介してMS-SQL Serverをターゲットにすると、この全く同じコードがデッドロックを引き起こします。

デッドロックは、Oracleドライバは、デッドロックが発生しないのはなぜ、このような安っぽいコード

  • の予想される動作ですか?内部で.ConfigureAwait(false)を使用していますか?

  • 私はそうのような適切

呼び出しをプログラミングする場合でも、望ましくない副作用があるかもしれないことを心配する必要があるOracleドライバが実際に微調整を使用している場合:

public class SomeController : Controller { 
    public async Task<ActionResult> SomeAction() { 
      var result = await new MyRepository.GetFirstFooAsync(); 
      [...] 
    } 
} 

私は」私はインターネットの知恵が.ConfigureAwait(false)を「部分的に」使用しているという印象を受けているので、他のすべての非同期呼び出し(もしあれば)で.ConfigureAwait(false)を使用しなければなりません。私は上記の勧告を正しく理解/解釈しているかどうかはわかりませんが、私は訂正して喜んでいます。私が心配している場合は、.ConfigureAwait(false)の部分的な使用が問題の原因となる例を提供することは非常に親切であり、複数のAsync()呼び出しが関係する場合に.ConfigureAwait(false)がどのように使用されるべきかの例を提供してください。

+0

あなたが適切にあなたの最後のコード例を経由して非同期を実装する場合、どのようにOracleが反応しませんか? –

+0

外見上は、Oracleとms-sql-serverの両方で、すべてが「async/await all way」アプローチで動作します。私はオラクルの下で働くという事実はすべてが大丈夫だと言っていないので、この質問をする傾向がありました。 Async/awaitコードには、基になるサードパーティのコード(ここでは、Async()経由で到達したoracle efドライバ)が100%正しく実装されていない場合に、デッドロックが発生する可能性があります。 – xDisruptor

+0

次に、実際に問題が発生するまで、async/awaitの使用を強くお勧めします。 –

答えて

0

ConfigureAwait(false)は、このデッドロックを防止しません。

私は、OracleがおそらくTask.Run(またはそれに類するもの)の中にラップされた同期コードよりも非同期であると推測します。

ConfigureAwait(false)はASP.NETコアでは不要です(同期コンテキストがないため)。アクションメソッドを終了した後にコンテキストが必要なため、アクションメソッド内で使用しないでください。

あなたはそれが両方のプロバイダで動作するかどうかを確認するために(私が持っていない)、これを試してみてください:

public class SomeController : Controller 
{ 
    public ActionResult SomeAction() 
    { 
     var synchronizationContext = SynchronizationContext.Current; 
     try 
     { 
      var result = new MyRepository.GetFirstFooAsync().Result; 
      [...] 
     } 
     finally 
     { 
      SynchronizationContext.SetSynchronizationContext(synchronizationContext); 
     } 
    } 
}