.NET4.5を対象とするASP.NETMVC4アプリケーションがあります。子アクションの1つは、HttpClientを使用してWebサービスを呼び出します。
IO HttpClient応答を待機しているので、コードをasync/awaitパターンに変換することは非常に理にかなっています。ただし、MVC4が子を実行しようとするとアクションを実行すると、次のエラーメッセージが表示されます。
非同期操作が完了するのを待っている間、HttpServerUtility.Executeがブロックされました。
一見すると、MVC4は子アクション内の非同期/待機をサポートしていないように見えます。残りの唯一のオプションは、同期コードを使用して実行し、非同期タスクで「待機」を強制することです。
ご存知のとおり、ASP.NETコンテキストの非同期タスクで.Resultまたは.Wait()に触れると、すぐにデッドロックが発生します。私の非同期ロジックはクラスライブラリにラップされているため、「await blah.ConfigureAwait(false)」トリックを使用できません。子アクションで「async」にタグを付けてawaitを使用するとエラーが発生し、awaitを構成できなくなることを忘れないでください。
この時点で私は隅に塗られています。 any MVC 4の子アクションで非同期メソッドを使用する方法はありますか?回避策のないフラットなバグのようです。
async
フレンドリーではないMVCの部分がまだあります。これらは将来的に対処されることを願っています。このためにConnectまたはUserVoiceの問題を作成してください。
私の非同期ロジックはクラスライブラリにラップされているため、「await blah.ConfigureAwait(false)」トリックを使用できません。
おそらくshouldクラスライブラリの呼び出しにConfigureAwait(false)
を追加する必要があります(可能な場合)。
別の解決策をハックすることもできます。 IfクラスライブラリメソッドがASP.NETコンテキストを必要としない場合は、スレッドプールスレッドに(a)待機を実行させることができます。
_try
{
var result = Task.Run(async () => { await MyHttpRequest(...); }).Result;
}
catch (AggregateException ex) { ... }
_
効果はConfigureAwait(false)
に似ています。MyHttpRequest
はスレッドプールコンテキストで実行されるため、完了時にASP.NETコンテキストに入ろうとはしません。
スティーブンの答えのフォーマットは私にはうまくいきませんでした(多分それは非同期noobの問題ですがねえ)。
強く型付けされた戻り値を取得するには、この形式で非同期式を作成する必要がありました。
Person myPerson = Task.Run(() => asyncMethodWhichGetsPerson(id)).Result;