ASP の処理を途中で停止させたいときは…?
SPECIAL
ASP の処理を途中で停止させたい
ASP でメールを大量送信するスクリプトを書いている人から、いろいろ事情がありまして、何かのときに処理を停止させることはで着ないかというお話を受けました。
それについて考えてみて、IIS とは別にメール送信処理を受け持つサービスプログラムなり COM コンポーネントなりを用意して、ASP からはそれに対する命令の実行と、実行状態の監視を行うのがスマートなやり方なんじゃないかなとも思いましたけど、それだと大掛かりになりすぎてしまうので、ASP だけで何とかならないか、ちょっと考えを巡らせてみることにしました。
結局のところは、何も見出せてはいませんけれど。
プロセスビュアで確認してみる
とりあえず、ローカルコンピュータ (OS: Windows XP Professional) 上の IIS にて、次のような ASP ページを用意してみました。
<html>
<head>
<title>LOOP TEST</title>
</head>
<body>
<%
Dim LoopCount
Dim i
LoopCount = 100000
Response.Write "ループを開始します。"
For i = 1 To LoopCount
Response.Write "ループカウント: " & CStr(i) & "<br>"
Response.Flush
Next
Response.Write "ループが終了しました。"
%>
</body>
</html>
内容としては、このページをブラウザを用いて IIS 経由でアクセスすると、100,000 回のループ処理が行われて、繰り返し回数を HTML として出力するというものです。出力は 1 行ごとに Response.Flush を実行してバッファーから送り出しているので、結果が順次ブラウザで確認できるようになっています。
これを実行してみると、たとえローカルコンピュータ上のサイトであってもそこそこ時間はかかる感じでした。
ただ、なんとなくなんですけど、ブラウザの停止ボタンを押すと、なんだか処理がちゃんと打ち切られているような気がするのですけど…。
そう思ってプロセスビュアで IIS (inetinfo.exe") の CPU 利用率を確認してみたところ、ページ表示中は 12% くらいだった IIS の CPU 利用率が、ブラウザの停止ボタンを押したとたんに 3% 程度となって、そして 0% に落ち着きました。更新ボタンを押しても 1 秒程度の待ち時間こそあるもののすぐに最初から再開されるので、なんとなくですけど既に中断されていそうな感じはします。
ただ、もしかしたら IIS のバージョンやブラウザによって違うかもしれないので、なんとも言えないところですけど。
セッションを使ってみるとどうなるか
IIS はセッションという概念を用いて、複数のページを一連の流れとしてみることが出来るようになっています。
実際のところは Cookie を利用してクライアントを管理して、同じクライアントからの要求であった場合には、変数とかを内部で保持したまま継続して利用することができます。これを利用したら…、もしかしたら処理中のページに何か関与できるかな…と思って試してみることにしました。
試せることとしては、ループページ表示中に別ウィンドウでセッションをリセットしてどうなるかと、セッション内で共通して利用できる Session 変数の値を変更するとどうなるかといったところでしょうか。
とりあえずセッションをリセットするとどうなるか、やってみようと思います。
そのためにまずは、セッションをリセットするページを用意してみることにします。とりあえず "session.abandon.asp" という名前にして、次のような内容のページを作成してみることにしました。
<html>
<head>
<title>Session の初期化</title>
</head>
<body>
<% Session.Abandon %>
<p>セッションを初期化しました。</p>
</body>
</html>
そして先ほど作成したループページの最初の方に、このページを別ウィンドウで表示するための記載を加えます。
<a href="session.abandon.asp" target="_blank">Session Reset</a>
このようにしてループページを表示して、ループ処理の最中に "Session Reset" リンクをクリックしてみましたが、別ウィンドウは表示されるものの応答待ちといった感じで、ページの内容が表示される感じはありませんでした。ループページをブラウザの 「停止」 ボタンで止めてみれば、それにあわせたかのように、セッションを初期化するページの表示が完了しました。
この感じだと、とりあえずループページにかかりっきりになってしまっている感じですね。
念のためループページを Session 変数の値を使ってループさせるようにした上で、セッションのリセットページへアクセスしてみましたけど、それによってループページのカウントが変わる感じもありませんでした。リセットページが待ち状態になってるせいもあるのでしょうけど、ちょっと調べてみた感じだと Session.Abandon を実行しても即座にセッションの値がリセットされるわけではなくて、ページの処理が終わって初めてそうなるような感じがしました。
だからもしかすると、もし上手くリセットできたとしても、セッション変数を頼りにループ処理を停止させることは難しいのかもしれないです。Static 変数で値を保持した COM でも作成してそれを使えば各ページで値を共有することは出来るかもしれないですけど、その値を調整するにも待たされてしまうようではどうにもならなそうな感じですね。
意識的に止めるためには、やっぱり外部プログラムとの連携が必要なのでしょうか。
もしかしたら意外と簡単な方法があるのかもしれないですけど、とりあえずはそんな感じの見通しでした。ブラウザの停止ボタンでなんだか止まる気もしますし、あまりに処理が長い場合はある程度すれば IIS の方が勝手にタイムアウトしてくれるはずなので、普通はあまり困ったことにはならないような気がするので、今回はこのくらいで調査終了ということにしておきます。