- PR -

ASP.netWEBサイトで”スレッドを中止しようとしました”エラーが発生

投稿者投稿内容
FOX2
会議室デビュー日: 2007/03/16
投稿数: 10
投稿日時: 2007-03-16 18:05
【環境】
Webサーバ:Windwos Server 2003 Standard
ファイルシェアサーバ:Windows Server 2003 Enterprise(MSCluster / DFS)
DBサーバ:Windows Server 2003 Enterprise
SQL Server 2000 Enterprise
.netFramework1.1
ASP.net(VB)のWebサイトシステムです。

始めて利用させていただきます。

現在保守を行っているシステムで稀に以下の2つのエラーが発生します。
1)「スレッドを中止しようとしました」
2)「プロセスはファイル "〜〜.xml" にアクセスできません。このファイルは別のプロセスが使用中です。」

【サイトについて】
このサイトは、一般に公開しているWebサイトで、DBに入っているデータを単純に
表示させるだけのサイトです。画面はすべてascx化しており、ロジックはすべてascx上で持っています。
また、ルートのフォルダから下すべてをファイルシェアサーバに配置しています。

【エラーの事象について】
現象としては、1)、2)共ごく稀(平均して1ヶ月に2〜3回程?)に
上記のエラーを同タイミングで出力することがあります。1)のみの場合もありますが、
2)が出力される時は1)は今のところ必ず付いてきています。
発生は精々1分〜3分の間パラパラと出力されその後何もせずともエラーは出力されなくなります。

【PGでエラーを出力している箇所】
1)はascxにて、データ取得の為ストアドをコールしている箇所で発生しています。
(SqlClient.SqlCommand.ExecuteReaderにて実行)
ちなみに、ascxは複数ありますが、どのascxも似たり寄ったりで基本的には同じこと
(ストアドコール->データ取得->データバインド)をしています。
すべてのascxが吐いているのを確認はしていませんが、複数個のascxが出力している為、どれかの記述で
バグを持っているというのでは無い様に思います。また、当プログラムではResponse.Endなどを行っている
箇所ではすべてExceptionをスルーさせる処理を入れているのでリダイレクト時のスレッドエラーでは
ありません。

2)は、マスタ情報をXMLファイルで保持しており、そちらの読込み箇所で発生しています。
が、ファイルは初回のみ読込みキャッシュにセットする為、ファイルの更新が無い限り
(CacheDependencyにて該当ファイルを指定)キャッシュから読み込まれるはずです。
勿論、エラー発生時にファイルを操作していたなどはありません。
また、当ファイルにはリードのみしか行いません。


テスト環境でテストしても未だ再現もせず、色々とサイト等で調べてみたのですが分からずいたのですが、
現時点ではファイルサーバが一時的に見れなくなっっていることにより出力しているものではないかと
あまり根拠なく思い始めています。
調査方法として、
・ネットワーク関係のパフォーマンスモニタログを採取する
位しか思いつかないのですが、この様に調べるべき/そもそも見当違い・・等々のご意見頂けるならば
お願いしたく存じます。


※説明が下手で申し訳ないです。情報の不足などがあれば追って補足致しますのでご指摘下さい。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-03-16 18:33
過負荷状態で長期間テストした?
スレッド中止は特殊だから、握り潰せないよ。
_________________
FOX2
会議室デビュー日: 2007/03/16
投稿数: 10
投稿日時: 2007-03-16 18:56
Jittaさん

ご指摘ありがとうございます。
一応、テスト環境でWASTを使って100スレッド/5日間というのは
してみたのですが、今のところ再現していません。
期間的にも負荷的にも不足は否めないのでもうちょっと長いスタンスで
やってみます。

ちなみに、
Response.Endとかをしている箇所では一番上のメソッド(Page_Load)まで
ThreadAbortExceptionを無視するようにしているのですが、全メソッドで
この処理を入れておくべきなんでしょうか・・・?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-03-16 20:55
無視とは、どの様にして、実現していますか?


あと、リダイレクトやトランスファーをして発生したものを無かったことにしてしまったら、どういうことになるか、わかってやってますか?
_________________
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-03-18 09:11
引用:

ThreadAbortException クラス<microsoft.com>より:
スレッドを破棄するために Abort メソッドが呼び出されるときに、共通言語ランタイムは ThreadAbortException をスローします。
ThreadAbortException は、キャッチできても、 catch ブロックの末尾でもう一度自動的に発生する特殊な例外です。この例外が発生すると、ランタイムは、スレッドを強制終了する前に finally ブロックをすべて実行します。スレッドは、 finally ブロックで無制限に計算を実行できるため、スレッドを中止させるために Join メソッドを呼び出す必要があります。 Join は、スレッドが実際に実行を停止するまで戻らないブロッキング呼び出しです。


 普通に
try {
 何か処理
catch (ThreadAbortException) {
 // 握りつぶすため、何もしない
}
としていても、catch ブロックの終了時にもう一度発生します。

 Redirect や Replace は、今行っている処理を中断(Abort)して、ほかのページを処理するようにします。したがって、今行っている処理は、中断させなければなりません

 なので、「どうやって中断しようとしているのか?」「中断したらどうなるかわかってやっているのか」と、聞いています。


BBコードを間違った

[ メッセージ編集済み 編集者: Jitta 編集日時 2007-03-18 09:12 ]
NAL-6295
ぬし
会議室デビュー日: 2003/01/26
投稿数: 966
お住まい・勤務地: 東京
投稿日時: 2007-03-18 13:55
NAL-6295です。

たぶん過去ログにもあると思うのですが(結構、昔から目にするので)

[PRB] Response.End、Response.Redirect、または Server.Transfer メソッドを使用すると ThreadAbortException が発生する
http://support.microsoft.com/default.aspx?scid=kb;ja;312629

FOX2
会議室デビュー日: 2007/03/16
投稿数: 10
投稿日時: 2007-03-19 09:36
Jittaさん、NAL-6295さん

すみません、ご返信が遅くなってしまいました。
Jittaさんには補足まで頂き申し訳ないです。

>Jittaさん
「無視」は、仰るとおりCatchの中で何もしないというやり方をしています。
その時、呼出し元のメソッド(Page_Load)に制御が返った所でまたThreadAbortException
が発生するのは認識していたのですが、「Thread.ResetAbort();」等 の書き方を知らず、
結局、呼出し元までの全メソッドでCatchし、無視するという記述をしてしまっています。
スレッドに関しては(ASP.netに関してもですが)ろくに知識をもっていないので、
上記位の認識です。

>Jittaさん、NAL-6295さん
「Response.End、Response.Redirect、または Server.Transfer を行うと、
ThreadAbortExceptionが発生する」というのは一応は認識はしておりました。
その為、Response.End等の記述をしている箇所では(あるべき対処方法ではない
とは思いますが)上記の通り対応はしております。
ただ今回発生しているのが、「SqlClient.SqlCommand.ExecuteReader」の実行及び
バインドのみを行っているメソッドにて発生している為悩んでおります。
また、常に発生するものでは無く、稀に発生するという点も?な状況です。

取り合えず、WASTで過負荷状態を作り出し再現テストを実施中です。
(再現テストは土日から流しっぱですが今のところ再現していないです)
今回の障害とは別と考えているのですが、Response.Endなどの記述も今回の対応で
併せて直してしまおうと思っています。


もし、他にもお気づきのところなどあればご指摘頂ければと思います。
よろしくお願いします。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-03-19 21:41
ん〜。。。なんか、勘違いというか、すれ違いというか(^-^;
引用:

「無視」は、仰るとおりCatchの中で何もしないというやり方をしています。
その時、呼出し元のメソッド(Page_Load)に制御が返った所でまたThreadAbortException が発生するのは認識していたのですが、「Thread.ResetAbort();」等 の書き方を知らず、結局、呼出し元までの全メソッドでCatchし、無視するという記述をしてしまっています。


 だから、なぜ、ThreadAbortException を握りつぶす必要があるのですか?
 NAL-6295さんが提示されている PRB は、Response.Redirect を書いたけど、その後ろに実行させたいコードがある、というときのものです。
 ただし、私としてはそのような設計が悪く、あるいは finally ブロックに入れるべきでしょう。
コード:
try {
    Response.Redirect("somepage.aspx");
} finally {    // finally は実行される
    後処理();
}


 ついでに、NAL-6295さんによる名言も紹介。
「むやみにキャッチしないでね。キーパー以外はハンドで反則ですよ。」
 私の勝手な追加。
「キーパーでも、ペナルティ エリア外では反則ですよ。」

 単に「例外を発生させたくない」ということなら、逆に Redirect を使わないようにコーディングし直した方がいいでしょう。「例外ログに記録したくない」ということなら、ログ記録部で弾けばいいだけです。あるいは、ユーザさんに「システム的に必要があって発生し、記録されます」と説明して、運用上逃げてもらえばいいと思います。


 (2)の方は、別スレにする?

_________________

スキルアップ/キャリアアップ(JOB@IT)