web-dev-qa-db-ja.com

ASP.NET MVC4非同期子アクション

.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の子アクションで非同期メソッドを使用する方法はありますか?回避策のないフラットなバグのようです。

28
ShadowChaser

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コンテキストに入ろうとはしません。

33
Stephen Cleary

スティーブンの答えのフォーマットは私にはうまくいきませんでした(多分それは非同期noobの問題ですがねえ)。

強く型付けされた戻り値を取得するには、この形式で非同期式を作成する必要がありました。

Person myPerson = Task.Run(() => asyncMethodWhichGetsPerson(id)).Result;
6
David Spence