表題のマイクロソフトのサポート技術情報があることを知った。
http://support.microsoft.com/default.aspx?scid=kb;ja;JP312629
ASP.netで 例えばログインの処理などで、
パスワードが正しければ“メニュー”を表示するが
間違ったパスワードだとログイン画面を表示したまま。
なんて処理はたぶんにあると思う。
そこになにげなく
と書いたりすることもあるだろう。
結果、画面は新たな遷移先の画面内容が表示されるので、
気が付くことはないのだけれども、
実は知らない間に裏でこっそり ThreadAbortException が発生していたというのだ。ひー。
試しに、こうして実行してみよう。
Response.Redirect("Menu.aspx")
Catch ex As Exception
System.Diagnostics.Debug.WriteLine(ex.ToString)
End Try
速度にどの程度まで影響しているか等は調べていないのだけれど、
もともと Exceptionがうんちゃらという画面が出るわけでもないので、
そのまま無視して使うというのも手だと思う。
この症状を気にして回避する場合には、以下のようにするらしい。
是非はともかく、この動作はマイクロソフトによると『仕様』なのだそうだ。
さて、ここまでは前置き。
通常 Webアプリケーションで CSVダウンロードをしたり、動的に画像を作成/選択して
表示したりする場合には最後に Response.End を使うことになるというのが一般とされている。
ただ、実はこの Response.End でも ThreadAbortException が発生する。
で、ファイルの読み書き処理や、データベースアクセス処理なんかに
はしょって大雑把な Try / Catch を仕掛けている場合、ファイルや DBのアクセス時ではなく
Response.End で Exception が発生したりするのだな。
もう一度。
>是非はともかく、この動作はマイクロソフトによると『仕様』なのだそうだ!!
というわけで、Response.End における ThreadAbortException の扱いは、以下。
1.ThreadAbortException は catch しても無視する。
ただしこの ThreadAbortException は、キャッチできても、 catch ブロックの末尾で
もう一度自動的に発生する特殊な例外(by Help)、
とのことで呼び出し側のメソッドにも Try / Catch がある場合は再度 catch されてしまうゆえ
無視し続けなくてはいけない。
2.Try / Catch ブロック中に Response.End を入れない。
Response.End だけを除外するにはかなり高度なテクが必要でわ?
3.Response.End の代わりに、HttpContext.Current.ApplicationInstance.CompleteRequest メソッドを呼び出す。
(by サポート技術情報)
よくわかりませんが、こんなん使って良いんですか?(日本語情報が無さすぎ)
(2005/08/31:追記) ただし困ったことに HttpContext.Current.ApplicationInstance.CompleteRequest
は、Response.Endと等価ではなく、処理が途中で終わるわけではない。
例えば Postbackしたままの画面でダウンロード処理を行い、上記メソッドを呼び出すと
ダウンロードするデータの内容の末尾に、本来 Postback後に表示されるはずの
画面内容(HTML)が付け足しで送って来られてしまう。非常にいらん。
ということで、考えられる回避策、
その1.そんな設計(画面遷移)をするな。
JavaScript:window.open(~) とかしてから呼べ?
その2.HttpContext.Current.ApplicationInstance.CompleteRequest の後に
Response.Closeをしろ。
とりあえずブラウザとの接続を切っちゃえば送ってこられなくなる。
(なんか問題の解決を間違っているような気も)
その3.やっぱり Response.End を使う。
ひゃー
その4.Render系のイベントをごにょごにょする(???)