28

.NET 4.5 をターゲットとする ASP.NET MVC 4 アプリケーションがあります。子アクションの 1 つは、HttpClient を使用して Web サービスを呼び出します。

HttpClient の応答を待って IO をブロックしているため、コードを async/await パターンに変換することは非常に理にかなっています。ただし、MVC 4 が子アクションを実行しようとすると、次のエラー メッセージが表示されます。

非同期操作が完了するのを待っている間に、HttpServerUtility.Execute がブロックされました。

一見すると、MVC 4 は子アクション内で async/await をサポートしていないように見えます。残っている唯一のオプションは、同期コードを使用して実行し、非同期タスクで「待機」を強制することです。

ご存知のように、ASP.NET コンテキストの非同期タスクで .Result または .Wait() に触れると、すぐにデッドロックが発生します。私の非同期ロジックはクラス ライブラリにラップされているため、「await blah.ConfigureAwait(false)」トリックを使用できません。子アクションに「async」のタグを付けて await を使用するとエラーが発生し、await を構成できなくなることを覚えておいてください。

この時点で私は隅に追いやられています。MVC 4 子アクションで非同期メソッドを使用する方法はありますか? 回避策のない完全なバグのようです。

4

2 に答える 2

34

フレンドリーではない MVC の部分がまだありasyncます。これらについては、今後対応されることを願っています。これについては、Connect または UserVoice の問題を作成してください。

私の非同期ロジックはクラス ライブラリにラップされているため、「await blah.ConfigureAwait(false)」トリックを使用できません。

おそらく、クラス ライブラリの呼び出しに追加する必要があります (可能な場合)。ConfigureAwait(false)

代替ソリューションをハックすることもできます。クラス ライブラリ メソッドが ASP.NET コンテキストを必要としない場合は、スレッド プール スレッドに (a) 待機をさせることができます

try
{
    var result = Task.Run(async () => { await MyHttpRequest(...); }).Result;
}
catch (AggregateException ex) { ... }

効果は次のようになりConfigureAwait(false)ます。MyHttpRequestスレッド プール コンテキストで実行されるため、完了時に ASP.NET コンテキストに入ろうとしません。

于 2012-10-05T09:23:42.707 に答える
7

スティーブンの回答の形式は、私にとってはうまくいきませんでした(非同期初心者の問題かもしれませんが、ねえ)。

厳密に型指定された戻り値を取得するには、この形式で非同期式を記述する必要がありました。

Person myPerson = Task.Run(() => asyncMethodWhichGetsPerson(id)).Result;
于 2016-01-27T07:47:54.770 に答える