1. ホーム
  2. asp.net

[解決済み] IISで長時間実行するジョブにスレッドを使用できますか?

2023-04-23 23:03:53

質問

ASP.Netアプリケーションでは、ユーザーがWebページ上のボタンをクリックすると、イベントハンドラを通じてサーバー上のオブジェクトがインスタンス化され、そのオブジェクトのメソッドが呼び出されます。 このメソッドは、外部システムに行って処理を行うため、時間がかかることがあります。そこで、このメソッド呼び出しを別のスレッドで実行し、ユーザーに "リクエストが送信されました" でコントロールを返せるようにしたいと思います。 私はこれをfire-and-forgetとして行うことに合理的に満足していますが、ユーザーがオブジェクトの状態をポーリングし続けることができれば、さらに素晴らしいことでしょう。

私が知らないのは、IIS がユーザー セッションが終了した場合でも、私のスレッドを実行し続けることを許可するかどうかということです。 想像してみてください、ユーザーがイベントを発生させ、サーバー上でオブジェクトをインスタンス化し、新しいスレッドでメソッドを発生させたとします。ユーザーは "Your request has been submitted" のメッセージに満足し、ブラウザを閉じます。最終的に、このユーザーのセッションはIIS上でタイムアウトしますが、スレッドはまだ動作しており、作業をしているかもしれません。IIS はスレッドを実行し続けることを許可するのでしょうか、それともユーザー セッションが終了した時点でスレッドを停止してオブジェクトを破棄するのでしょうか?

EDIT: 回答とコメントから、これを行う最良の方法は、長時間実行する処理を IIS の外部に移動することであると理解しました。他のすべてとは別に、これは appdomain のリサイクルの問題を処理します。実際には、限られた時間でバージョン1を立ち上げる必要があり、既存のフレームワーク内で動作させる必要があるため、サービス層を避けたいと考えており、そのためIIS内でスレッドを起動させるだけにしておきたいと考えています。実際には、ここでの "long running" は数分で、ウェブサイトの並行性は低いので、大丈夫でしょう。しかし、次のバージョンでは、間違いなく別のサービス レイヤーに分割する必要があります。

どのように解決するのですか?

望むことを実現することはできますが、一般的には悪い考えです。 いくつかの ASP.NET ブログおよび CMS エンジンは、共有ホスティング システムにインストール可能で、インストールする必要のある Windows サービスに依存しないようにしたいため、このアプローチをとっています。 通常、アプリの起動時に Global.asax で長時間実行するスレッドをキックオフし、そのスレッドでキューに登録されたタスクを処理します。

IIS/ASP.NET が要求を処理するために利用できるリソースを減らすことに加えて、AppDomain がリサイクルされるときにスレッドが強制終了されるという問題もありますし、飛行中のタスクの持続性に対処し、AppDomain が回復したときに作業を再開しなければなりません。

多くの場合、AppDomain はデフォルトの間隔で自動的にリサイクルされ、web.config などを更新した場合にもリサイクルされることを覚えておいてください。

スレッドがいつでも停止されることの永続性とトランザクションの側面を処理できる場合、ある間隔でサイトにリクエストを行う外部プロセスを持つことによって、AppDomain のリサイクルを回避することができ、サイトがリサイクルされた場合、X 分以内に自動的に再開することが保証されています。

繰り返しますが、これは一般的に悪い考えです。

編集部:このテクニックを実際に使っている例をいくつか紹介します。

コミュニティ サーバー Windows サービスとバックグラウンド スレッドを使用して、スケジュールされた間隔でコードを実行する Web サイトの初回起動時にバックグラウンド スレッドを作成する

EDIT (from the far distant future) - 最近では、私なら ハングファイア .