2017-09-22 7 views
0

ASP.NET MVCアプリケーションには3つのレイヤーがあります。最初のレイヤーから、私は2番目のレイヤーでメソッドを呼び出しています。このメソッドは、3番目のレイヤーで、Webサービスを呼び出します。以下はコードです。両方の層(2および3)を溶液中にClass Libraryとして加える。デッドロック待機中結果

namespace Web.Controllers // Layer 1 
{ 
    using Web.Services; 
    // other usings... 
    public class Controller1 
    { 
     [HttpPost] 
     public JsonResult Search(SomeObject request) 
     { 
      Service service = new Service(); 
      var result = service.Search(request).Result; 
     } 
    } 
} 

namespace Web.Service // Layer 2 
{ 
    using Web.Library; 
    // other usings... 
    public class Service 
    { 
     public async Task<SomeType> SearchFlights(SomeObject requestModel) 
     { 
      SomeObjectReturn result = new SomeObjectReturn(); 

      Library library = new Library(); 
      var result = await library.Search(requestModel); 
      return result; 

     } 
    } 
} 

namespace Web.Library // Layer 3 
{ 
    public class Library 
    { 
     public async Task<SomeObjectReturn> Search(SomeObject request) 
     { 
      // here I call Sabre service to get the result... 
      SomeObjectReturn obj = new SomeObjectReturn(); 
      RestClient restClient = RestClientFactory.Create(); 
      IActivity activity = new InstaFlightsActivity(restClient, requestModel); 
      Sabre.Library.Workflow.Workflow workflow = new Sabre.Library.Workflow.Workflow(activity); 
      SharedContext sharedContext = await workflow.RunAsync(); 
      // map sharedContext to SomeObjectReturn 
      return obj; 
     } 
    } 
} 

ここで、デッドロックがawait workflow.RunAsyncにある理由はわかりません。私はまた、に.ConfigureAwait(false)を試しました。とにかくデッドロックが発生しています。コードに何が問題なのか分かりません。

ところで、私はControllerに以下のように変更を加えました。結果が出ました。

public async Task<JsonResult> Search(SomeObject request) {... 

の代わりに、

+0

'.Resul'と' .Wait() 'は*ブロッキング*コールです。 –

+0

_私は何がコードに間違っているのか分かりません.'Result'を使うことで、あなたのコードは、スレッドがhisselfの完了を待っている状態になります。呼び出しメソッドは、タスクが完了したときに待機し、完了したタスクはスレッドがアイドル状態になるのを待って完了を通知します。 – Fabio

+0

2つのコメント:1.すべての 'ASP.NET'コントローラは' Controller'または 'ApiController'(web apiの場合)から継承しなければなりません。 2.すべてのコントローラのアクションは '非同期タスク 'でなければなりません。' –

答えて

1

Resultのコールでデッドロックが発生します。非同期APIを使用すると、async/awaitですべての処理を行う必要があります。そうしないと、デッドロックが発生する可能性があります。コントローラコードを以下のように変更すると、問題は消えてしまいます。

[HttpPost] 
public async Task<JsonResult> Search(SomeObject request) 
{ 
    Service service = new Service(); 
    var result = await service.Search(request); 
} 
+0

OPは既に質問で言及したものと同じですか? – Fabio

+1

@Fabio、いいえ、OPは同期*メソッドを使用し、同期化コンテキストをブロックするための '.Result'を使用しました。これは、 'await'への呼び出しがそのコンテキストに戻るのを防ぎます。したがって、デッドロックです。最善の解決法*はすべてを非同期にすることです。 'ConfigureAwait(false)'を使用しても、デッドロックを回避してもスレッドを無駄にすることはありません –

+0

@PanagiotisKanavos、OPの最後の文:_BTW、私はコントローラで以下のように変更しました。理由を説明してください – Fabio

関連する問題