4

.NET 4.5のさまざまな非同期機能についてはまだ理解していませんが、何か面白いことに遭遇しました。私のMVCコントローラーで次のことを考えると、(1)と(2)を実行すると異なる結果が得られます

public ActionResult Index() {
    var stuff = SomeExpensiveFunction();
    return View(stuff);
}
private byte[] SomeExpensiveFunction() {
    string url = "http://some-url.../";

    // (1)
    var wc = new WebClient();
    return wc.DownloadDataTaskAsync(url).Result;

    // (2)
    var hc = new HttpClient();
    return hc.GetAsync(url).Result.Content.ReadAsByteArrayAsync().Result;
}

表面上、それらは同じように見えます-とは両方ともWebClient.DownloadDataTaskAsyncHttpClient.GetAsync返すasyncメソッドTaskです。WebClientバージョンが返されるTask<byte[]>間にHttpClientバージョンが返さTask<HttpResponseMessage>れ、バイトを掘り下げる必要がありますが、.Resultどちらの方法でも呼び出しています。これは、関数を終了する前に完了すると予想されます。

(1)を使用すると、。で黄色の画面が表示されAn asynchronous operation cannot be started at this time...ます。(2)を使用すると、すべてが正常に機能します。

スタック全体を変更しasyncて、コントローラーメソッド自体とを使用できSomeExpensiveFunctionます。すべてが正常に機能します。しかし、私は(1)に根本的な問題があるのか​​、それともWebClientMVCを使用する際の一般的な問題に問題があるのか​​を理解しようとしています。何かご意見は?

編集:この例では、実際には非同期で何もしていないので、これらの呼び出しの同期バージョンを使用できることを知っています-これは、より大きなコードベースに基づく単なる例です。

4

2 に答える 2

1

100%確信はありませんが、これは非同期メソッドの不適切な使用が原因である可能性があります。Resultを呼び出して非同期メソッドを同期的に使用することは想定されていないため、この動作が発生している可能性があります。

于 2013-04-01T20:04:34.063 に答える
1

あなたはASP.NETのSynchronizationContextにファウルしました。WebClientの例を機能させるには、コントローラー全体を非同期にする必要があります。これを試して:

public async Task<ActionResult> IndexAsync() {
    string url = "http://some-url.../";
    using (var wc = new WebClient())
        return View(await wc.DownloadDataTaskAsync(url));
}

非同期コントローラーの概要については、http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4およびhttp://www.tugberkugurlu.com/を参照してください。 async / awaitパターンのデッドロック効果の説明については、archive/asynchronousnet-client-libraries-for-your-http-api-and-awareness-of-async-await-s-bad-effectsを参照してください。

于 2013-05-24T10:29:32.657 に答える