3

私はNugetパッケージEsri.ArcGISRuntimeを持っていて、私のWeb API 2コントローラの1つにメソッドQueryTask.ExecuteAsyncを呼び出す必要があります。私は私のプログラム/サービスに完璧に動作ConfigureAwait(false)でもWebAPIデッドロックで非同期メソッドを同期呼び出す

private QueryResult ExecuteSync() 
    { 
     var queryResults = ExecuteAsync(); 
     queryResults.Wait(); 
     return queryResults.Result; 
    } 

    private async Task<QueryResult> ExecuteQueryTaskAsync() 
    { 
     var queryTask = new QueryTask(_uri); 
     return await queryTask.ExecuteAsync(_query).ConfigureAwait(false); 
    } 

のようなラッパーを使用していますマイライブラリのC#コードでのように、何の同期カウンタの一部はありません。しかし、ExecuteSyncをWeb API 2コントローラーで使用すると、これは完全にフリーズし、応答を返さないことがあります。

私はいくつかの研究を行い、犯人がここで言及されていると信じています http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

私は絶対に非同期機能を使用する必要はありません。上記の関数は、この1つのWeb API呼び出しをサポートするためだけに、非同期メソッドをバブルアップするライブラリクラスの主要なオーバーホールであるように、4ラッパーのようにコアで隠されています。

私が上で)私は(それが

+0

あなたは 'await'を使用しなければなりません。read [this](http://stackoverflow.com/questions/13140523/await-vs-task-wait-deadlock) – Legends

+0

@AlexeiLevenkov私はあなたが"内部同期コンテキスト"私はそれがより多くの内容を必要とするか、公式の答えのより多くになると思うコメント。リンクdoesntは実際に私のWeb APIのコントローラの例で調整されていません。まだ回避策として何をしているのか分かりません – ParoX

+0

あなたは既に 'ConfigureAwait(false)'を持っています...コードはデッドロックしてはいけません(タイトルが変更され、重複が間違っていました)。デッドロックが発生したときにスレッドがスタックした場所を調べることをお勧めします。また、問題がライブラリに関連していないことを確認するために、非常に基本的な非同期メソッド( 'Task.Delay(1000)')を試してください。 –

答えて

9

私は絶対にこの機能を非同期に使用したくないです。

私はそれを言います。非同期コードが最適なソリューションです。実行している操作は非同期であり、同期APIを公開することはせいぜい問題になります。

時間がかかりますか?確かに。しかし、あなたのコードはより良いものになるでしょう。

私は自分の欠点と一緒にすべての既知のハックをカバーan entire article on the subject of brownfield async developmentを、持っている

回避策/ハック/提案

を探しています。

Console/Win32Serviceスタイルのアプリケーションで動作することを考慮して、非コアASP.NET をWebApiから呼び出す場合は、スレッドプールハックが役立つはずです。それは次のようになります。

private QueryResult ExecuteSync() 
{ 
    return Task.Run(() => ExecuteAsync()).GetAwaiter().GetResult(); 
} 

アイデアが要求コンテキストの外で、ExecuteAsyncは、スレッドプールのスレッドで実行されていることです。要求スレッドは、非同期処理が完了するまでブロックされます。

+0

スレッドプールのハックが機能しました。それは私のcustomAttributeのコントローラー上で奇妙な問題を引き起こしますが、その属性を削除した後は正常に機能しました。私はクイックフィックスとして誰にでもこれをお勧めします。あなたが非同期で上向きになるまでの時間を見つけることができます(私は会う必要がある期限がありますので、これで節約できます)。ありがとう – ParoX

+0

ExecuteAsync()でこれを行うことはできませんでした。ConfigureAwait(false).GetAwaiter()。GetResult()? – victor

+0

@victor:いいえ。なぜ私の記事で説明しますか(https://msdn.microsoft.com/en-us/magazine/mt238404.aspx)。要するに、 'ConfigureAwait(false)'は設定するための 'await'がないので、何もしません。 –

0

あなたが.WAITを呼び出しているオブジェクトをデッドロック持っ同期この非同期メソッドを実行しないようにできるように、ウェブAPIのこの奇妙な現象を回避策/ハック/提案を探していますタスクでもあり、あなたはそれを設定していません。 .ConfigureAwait(false)をExecuteQueryAsyncの戻り値に追加します。

さらに、WebAPIを同期させることもできます。したがって、スタック全体を非同期にすると全体的に改善されます。

関連する問題