4

本 Pro ASP.NET MVC 4 には、非同期アクションの例があります。

public class RemoteDataController : AsyncController
{
 public async Task<ActionResult> ConsumeAsyncMethod() {
    string data = await new RemoteService().GetRemoteDataAsync();
    return View("Data", (object)data);
 }
}


public class RemoteService 
{
  public async Task<string> GetRemoteDataAsync() {
    return await Task<string>.Factory.StartNew(() => {
            Thread.Sleep(2000);
            return "Hello from the other side of the world";
        });
    }
}

私の質問は次のとおりです。タスクは、リクエストの処理にも使用されるスレッドプールのスレッドを使用するだけではありませんか?

同期 I/O バウンド メソッドがあるとします。このメソッドを Task.Run で呼び出してアクションで await しても、I/O バウンド メソッドのタスクが要求処理に使用できなくなったため、同時に処理できる要求が増えることはないと思います。または、リクエスト専用の別のスレッドプールがあり、アクションで Task.Run を使用すると、自動的に別のスレッドプールが使用されますか? 私が考えさせられたのは、この質問です:トラフィックの多いシナリオで ASP.NET で ThreadPool.QueueUserWorkItem を使用する場合、多かれ少なかれ、ライブラリからの非同期メソッドのみを使用する必要があり、これらのライブラリは独自のスレッド プールを使用します。

動作を設定することは可能ですか? ASP.NET WebForms でも同じように機能しますか?

4

1 に答える 1

4

それは本当に悪い例です。すぐに間違っていると思うことが3つありますが、主なものはあなたが指摘したとおりです。

タスクは、リクエストの処理にも使用されるスレッドプールのスレッドを使用するだけではありませんか?

はい、その例はそうです。

代わりに、次の例を検討してください。

public class RemoteDataController : Controller
{
  public async Task<ActionResult> ConsumeAsyncMethod() {
    string data = await new RemoteService().GetRemoteDataAsync();
    return View("Data", data);
  }
}

public class RemoteService 
{
  public async Task<string> GetRemoteDataAsync() {
    await Task.Delay(2000);
    return "Hello from the other side of the world";
  }
}

元の例では、 を使用してスレッド プール スレッドをブロックしましたThread.Sleep。これは、ASP.NET では完全に逆効果です。原則として、ASP.NETではTask.Factory.StartNeworを使用しないでください。Task.Run

対照的に、Task.Delayは当然のことながら非同期操作です。「自然に非同期」とは、I/O 操作が非同期であるのと同じように非同期を意味します (たとえば、HttpClientWeb 呼び出しの場合)。当然のことながら、非同期操作はスレッドを使用しないため、ASP.NET サーバーにとって魅力的です (スレッド プールへの負荷が軽減され、より多くのスケーリングが可能になります)。

これがどのように機能するかを考えるのは興味深いことです。私の例のように自然に非同期のメソッドを使用すると、スレッドはawait;に到達するまでリクエストを開始します。その時点で、リクエスト スレッドはスレッド プールに返され (!)、次の 2 秒間、そのリクエストを処理するスレッドはありません (ただし、リクエストは完了していません)。私はこの現象を「ゼロスレッド同時実行」と呼んでいます。がDelay完了すると、スレッドはリクエストの処理を再開し、リクエストを完了します。

ちなみに、AsyncControllerMVC3の残り物です。async/では必要ありませんawait

于 2013-10-30T22:42:01.523 に答える