3

ASP.NET MVC には、ユーザーが入力した電子メール アドレスのリストを受け取り、それらを検証してから、HTML およびテキスト バージョンの電子メール メッセージを各受信者に送信するアクションがあります。その後、ユーザーは感謝のページにリダイレクトされます。すべての電子メール メッセージが送信されるまで感謝ページへのリダイレクトを待機する必要がないため、Task.Factory.StartNew メソッドを使用して、実際に電子メール メッセージを送信する新しいタスクを開始し、正常に動作します。ユーザーはすぐにサンクス ページにリダイレクトされ、電子メール メッセージは別のスレッドで送信されます。したがって、すべてが思い通りに機能しますが、それでもマルチスレッドに関して次の質問があります。ここ数日、かなりの数の投稿を読みましたが、まだすべての回答が得られていません。

  1. タスク ライブラリはスレッド プールのスレッドを使用します

    タスク ライブラリを使用している場合は、ASP.NET スレッド プールのスレッドを使用して新しいスレッドを作成しています。つまり、アプリケーションの他の ASP.NET 要求を処理するために使用できるスレッドが 1 つ少なくなります。したがって、タスク ライブラリを使用しても、タスクを他の OS スレッドにオフロードして ASP.NET スレッドの使用を最適化することはできません。ユーザー エクスペリエンスのみが向上しますが、タスク ライブラリは、他の ASP.NET 要求を処理するために使用できる別のスレッドを使用します。したがって、唯一の結果は、ユーザーが待つ必要がないことです。

  2. 手ねじ

    本当に OS スレッドを使用したい場合は、新しいスレッドを明示的に開始する必要があります。ただし、新しい OS スレッドを開始したとしても、アプリケーションのスケーラビリティの向上を実際に確認するには、複数のコアまたはプロセッサを搭載したマシンが必要です。

  3. バックグラウンド スレッド プール

    一部の投稿では、ASP.NET スレッド プールと、バックグラウンド タスクに使用される別のアプリケーションのバックグラウンド スレッド プールについて説明しています。つまり、各 ASP.NET アプリケーションには、アプリケーション要求を処理するための 1 つのスレッド プールと、バックグラウンド タスクを処理するための別のスレッド プールがあります。私はそれが真実ではないと思います。各 ASP.NET アプリケーションにはスレッド プールが 1 つしかなく、このプールのスレッドは、アプリケーション要求とバックグラウンド タスクの両方を処理するために使用されると思います。これは、通常 1 つのスレッド (UI スレッド) しか実行されておらず、明示的に新しいスレッドを開始する必要がある Windows フォーム アプリケーションについて言えることです。しかし、ASP.NET は基本的にマルチスレッドです。

質問は次のとおりです。

  1. Dino Esposito による ASP.NET MVC 2 のプログラミングで非同期 MVC コントローラーについて読みました。彼は、非同期コントローラーが長時間実行されるタスクに OS スレッドを使用する方法について書いています。したがって、最初に ASP.NET 要求を処理した ASP.NET スレッドは、他の要求を処理するために解放されます。

    ここでは非同期コントローラーは必要ありませんが、私の質問は、私の例でそのような OS スレッドをどのように使用できるかです。別のスレッドを明示的に開始する必要がありますか、それとも Task ライブラリで何とか可能ですか?

  2. そのようなタスクを一部の OS スレッドにオフロードしたとしても、マシンにプロセッサが 1 つしかない場合、何かメリットがありますか? アプリケーションのスケーラビリティを本当に向上させるには、マルチコア マシンが必要だと思います。

4

2 に答える 2

4

あなたが抱えている本当の問題は、ASP.NETがいつでもAppDomainをリサイクルできることです。これが発生すると、バックグラウンドスレッドは極端な偏見で中止されます。スレッドプールスレッドを使用するか、独自のスレッドを開始するかは関係ありません。ASP.NETがスレッドを「認識」していない場合、AppDomainを破棄し、スレッドを取得する可能性があります。

「適切な」解決策は、WCFサーバーである別のWindowsサービスプロセスを用意することです。その後、Webアプリはコマンドをサービスに送信できます。サービスはコマンドを実行します。たとえば、いくつかの電子メールを送信します。

手っ取り早い方法は、メールを送信するWebアプリに非表示のアクションを設定することです。そのアクションへの非同期リクエストを開始し、結果を待たずに「ありがとう」ページを返します。ASP.NETは、要求がアプリ内からのものであることを気にせず、単に別の要求として扱います。ASP.NETは要求を「認識」しているため、要求を中止しません。

于 2012-04-09T11:03:58.707 に答える
1

[…]彼は、非同期コントローラーが長時間実行タスクにOSスレッドを使用する方法について書いています。したがって、最初にASP.NET要求を処理したASP.NETスレッドは、他の要求をサーバーに自由に使用できるようになりました。

まあ、それはあなたがその非同期コントローラーにどんなコードを持っているかに依存します。OSでコードを実行することもできThreadますが、実行する必要はありません。通常は、実行中にスレッドを使用しない非同期操作を開始します。そして、それが終了すると、結果はいくつかのThreadPoolスレッドで実行されます。

ここでは非同期コントローラーは必要ありませんが、私の質問は、このようなOSスレッドを例でどのように使用できるかということです。別のスレッドを明示的に開始する必要がありますか、それともタスクライブラリでこれもどういうわけか可能ですか?

を使用して新しいスレッドを開始できますTaskCreationOptions.LongRunning。これは新しいスレッドを開始することを保証するものではありませんが、実際にはそうなります。

そのようなタックを一部のOSスレッドにオフロードしたとしても、マシンにプロセッサが1つしかない場合、メリットはありますか?アプリケーションのスケーラビリティを本当に向上させるには、マルチコアマシンが必要だと思います。

そのスレッドがIOバウンド操作を同期的に実行する場合にメリットがあります。たとえば、電子メールの送信にかかる時間のほとんどは、CPUの使用ではなく、サーバーの応答を待つために費やされる可能性があります。その場合は、別のスレッドを使用すると(別のスレッドであろうと、別のスレッドであろうとThreadPool)、有益な場合があります。もちろん、その操作を非同期で実行すると、スレッドがブロックされないのでさらに良いでしょうが、それはコードをはるかに複雑にする可能性があります(そしてそれが不可能な場合もあります)。

あなたが書いた他のことに関して:

タスクライブラリを使用している場合は、ASP.NETスレッドプールのスレッドを使用して新しいスレッドを作成しています。つまり、アプリケーションの他のASP.NET要求を処理するために使用できるスレッドが1つ少なくなります。

はい、通常の状況では(デフォルトを使用し、TaskScheduler指定しない場合TaskCreationOptions.LongRunning)。ただし、これで問題が発生した場合は、ThreadPoolの制限を増やし、Thread短期間のタスク用に自分でsを作成しない方がよいでしょう。これは、スレッドの作成と破棄はコストのかかる操作であり、パフォーマンスが重要な場合は回避する必要があるためです。

[E]各ASP.NETアプリケーションには、アプリケーション要求を処理するための1つのスレッドプールと、バックグラウンドタスクを処理するための別のスレッドプールがあります。それは真実ではないと思います。各ASP.NETアプリケーションにはスレッドプールが1つしかなく、このプールのスレッドは、アプリケーション要求とバックグラウンドタスクの両方のサーバーに使用されます。

それよりも少し複雑ですが、はい、ASP.NET要求とThreadPoolタスク(デフォルトオプションを使用してThreadPool.QueueUserWorkItem()、またはTaskデフォルトオプションで開始することによって開始)は、同じスレッドプールで実行されます。

于 2012-04-09T11:15:14.363 に答える