- PR -

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

投稿者投稿内容
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2007-03-19 23:08
んーちょっとかみ合ってないと思うので。

リダイレクトやトランスファーでThreadAbortExceptionが発生するのは、
そこで実行を強制的に終了させるためで、まあ苦肉の策の仕様といったとこでしょう。

で、これに関してはFOX2さんのおっしゃってるようなやり方で無視で問題ありません。
ThreadAbortExceptionのCatch句で明示的にThrowするか、何もせずに自動で再スローさせるかってのはちょっとありますが。
※どっちでも実質あまり変わりませんが、一応明示的にThrowするほうが自然かな。
 VBなら例外フィルタで明示的に無視とかできたかも(C#では無理ですが)。

ただし、上記の無視って言ってるのは、例えば例外のログ出力とかを
共通でやっている箇所など、状況はやや限られます。
※普通の例外キャッチならそもそもException型でキャッチとかすることは
 そうそうないですよね?

で、予想してない箇所でThreadAbortExceptionが発生する件ですが、
例えば処理に時間がかかりすぎてタイムアウトした、などが考えられます。


XMLファイルの読み込みの共有モードとかはどうなってますか?
また、XMLファイルはどこに配置していますか?

キャッシュはアプリケーションドメインに保持されているので、
なんらかの事情でアプリケーションやプロセスのリサイクルが発生すると、
当然キャッシュも無効になります。

また、キャッシュの確認と読み込みを同期してないと、複数スレッドで同時に
キャッシュを確認し、同時に再読み込みを試みる可能性があります。
もしファイルを排他オープンしているならここで競合が発生します。


あとは、うーん、処理に時間がかかること自体は正常な動作でしょうか?
処理のタイムアウトはデフォルト1分50秒だったと思うので、それ以上かかるなら
ThreadAbortExceptionが発生するのは必然です。
どうしても時間がかかる処理を省けないなら、タイムアウトを伸ばすなどの対策も必要です。
※あまりお勧めはできませんが。


--追記
ThreadAbortExceptionを無視ってのは、例外をCatchして何かするところがあるから、
そこでThreadAbortExceptionを引っかからせてしまわないため(不要な例外処理をしないため)に
やってることですよね?
※無視が問題ないってのは、そういう前提で書いてます。

いろんな箇所でむやみに例外をキャッチしてるなら、それはそれで問題あり
(今回の話とは別の話ですが)です。

あと、ThreadAbortExceptionでResetAbortはしちゃだめです、普通は。
すでにされているように無視の方が正しいです、普通は。


[ メッセージ編集済み 編集者: なちゃ 編集日時 2007-03-19 23:18 ]
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2007-03-19 23:31
例外を潰してしまわないようにすべきなのは、皆さんが仰っている通りなので他の事で。

1)
ThreadAbortException の発生した原因が InnerException にあるかもしれません。調べてみてください。

2)
キャッシュに有効期限を設定していませんか?
キャッシュを作成するときにファイルと閉じていますか?
_________________
囚人のジレンマな日々
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-03-20 07:06
なちゃさんのおっしゃる 無視 は、キャッチしてもなにもしない、の無視でしょうか?

私は、例外が発生しなかったことにしたい、という意味で理解しているのですが。いたるところでキャッチしているような書き方がされているからです。


ここの認識があってなければ、話が収束するハズもなく。
で、どっち?>FOX2さん
_________________
NAL-6295
ぬし
会議室デビュー日: 2003/01/26
投稿数: 966
お住まい・勤務地: 東京
投稿日時: 2007-03-20 10:23
NAL-6295

Windows Server 2003 Service Pack 1 更新一覧
http://support.microsoft.com/kb/824721/ja

の中に

FIX: アクセス違反が OLE DB .NET データ プロバイダが使用される ThreadAbortException 例外により、発生します。
http://support.microsoft.com/kb/833742/

ってのがありますが、OLE DBじゃないから関係ないですよね。
まぁ、でもSPはあてておいたほうが良いですよ。

とはいえ、innerExceptionの内容が気になるところです。

[ メッセージ編集済み 編集者: NAL-6295 編集日時 2007-03-20 10:47 ]
FOX2
会議室デビュー日: 2007/03/16
投稿数: 10
投稿日時: 2007-03-20 19:23
Jittaさん、なちゃさん、囚人さん、NAL-6295さん

ご返信頂いているのにたびたび回答が遅くなり申し訳ありません。

>■Jittaさん
>なぜ、ThreadAbortException を握りつぶす必要があるのですか?
当サイトでは、Exceptionが発生したらイベントログに出力して、
それを集中監視システムで拾うという作りになっています。
そこで、各メソッドではほぼすべての処理をTry〜Catchで囲んでいて、
Exception発生はすべてログに出力するという形になっていました。
しかし、処理上、クエリストリングの改竄などでパラメータが不正な場合
別ページに遷移させる仕様があったため、クエリストリングのチェックメソッド
部分に関してはThreadAbortExceptionはExceptionのCatchとは別でCatchして
何もしないという対応にしてしまっています。
同様の対応を呼出し元メソッドのPage_Loadでも行っています。
握りつぶしている理由としては、”エラーとしてイベントログに記述したくない為”
になります。

※メソッド内のほぼすべてを無条件にTry〜Catchしていることなど設計がイマイチ
であることを知ってちょっと恥ずかしいです。メソッド全部を囲んでおけば、
何かエラーが発生した時にCatch出来ていいかな位にしか考えていませんでした。。
もうちょっと勉強していきたいと思います。。

>■なちゃさん
>処理に時間がかかりすぎてタイムアウトした、などが考えられます。
実は使用しているマシンはすべて他サイトとの共用サーバなので他サイトなどが
原因で「一時的に高負荷がかかった」などは普通にありえる状況ではあります。
一応、現在本番環境でパフォーマンスログを採取させていただいているので
次回再現した時には情報が採取できると思います。

>XMLファイルの読み込みの共有モードとかはどうなってますか?
>また、XMLファイルはどこに配置していますか?
XMLファイルはReadOnlyにしています。
読込みはStreamReaderのReadToEndを使用しています。
また、ファイルは共有サーバの参照ディレクトリ直下に置いています。


>あとは、うーん、処理に時間がかかること自体は正常な動作でしょうか?
決して正常な動作とはいえないです。データはDB、XML含めすべてReadOnly
だし、通常は1秒かからず表示されます。
尚、データは障害発生前後で更新等は発生していない為、特定のデータを参照したため
遅かったということも考えにくいです。

>■囚人さん
>1)
>ThreadAbortException の発生した原因が InnerException にあるかもしれません。調べてみてください。
InnerExceptionの知識が無いので調べてみます。
情報ありがとうございます!

>2)
>キャッシュに有効期限を設定していませんか?
>キャッシュを作成するときにファイルと閉じていますか?
有効期限の設定はファイルの更新で行うようにしていて、時間などではしていない、と思います。
----
Dim objCd As New System.Web.Caching.CacheDependency("XMLファイル")
Cache.Insert(XMLファイルの中身, XMLファイル名, objCd)
----
という感じで記述しています。

ワーカープロセスのリサイクルは行っていますが、1日1回でその時間も傷害発生時に近接していない
ため、そちらも関係なさそうに感じます。


>■NAL-6295さん
>まぁ、でもSPはあてておいたほうが良いですよ。
了解です。InnerExceptionについては上記の通り調べた上で報告します。


相変わらず説明ベタで申し訳ないですが、何卒よろしくお願いします。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-03-20 19:39
じゃぁ、ログする時に弾くほうが、効率が良く、後でメンテする人にも分かり易いですよね?

上がらないようにしようとすると、上げる可能性があるところ全てで処理を実装する必要があります。しかし、受け取るところで処理すると、一カ所に実装するだけです。
_________________
FOX2
会議室デビュー日: 2007/03/16
投稿数: 10
投稿日時: 2007-03-20 20:11
Jittaさん

>じゃぁ、ログする時に弾くほうが、効率が良く、後でメンテする人にも分かり易いですよね?
確かに仰るとおりです。

ただ、(知識不足のことなんですけど)
(1)「スレッドを中止しようとしました」がいつでも無視していいものか分からなかった
(2)Response.Redirect等以外で「スレッドを中止しようとしました」がでる処理が
(このサイトで)あると思っていなかった
ことから、ご説明していた様な記述となっておりました。

エラーの原因究明次第ですが、ログ出力箇所で弾くことも検討しようと思います。
ご指摘ありがとうございます。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-03-21 22:22
引用:

FOX2さんの書き込み (2007-03-20 20:11) より:

(1)「スレッドを中止しようとしました」がいつでも無視していいものか分からなかった
(2)Response.Redirect等以外で「スレッドを中止しようとしました」がでる処理が
(このサイトで)あると思っていなかった


1)
 じゃぁ、Redirect をする前に、「今からリダイレクトするよ」とログを出しておけば、読むときに「これは無視してもいい」とわかりますよね?

 あるいは、グローバルなところに・・・ASP.NET だあら、これは難しいか。


2)
 処理が長すぎれば出たように思いますので、全部を無視することは出来ないかもしれません。あぁ、なちゃさんが書かれていますね。
_________________

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