2007年06月25日

スレッド内で発生した例外 - System.Timers.Timer

   このエントリーをはてなブックマークに追加 Clip to Evernote
では、System.Timers.Timerを使った非同期処理の場合はどうなるんだろうか?
この Timerもスレッドが生成されるので、同じ動きだろうか?

public static void Example() {
System.Timers.Timer tm = new System.Timers.Timer();
tm.Elapsed += new System.Timers.ElapsedEventHandler(tm_Elapsed);
tm.Interval = 1000;
tm.Enabled = true;
Console.ReadLine();
Console.WriteLine("end");
}

static void tm_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
try {
Console.WriteLine("Hello World!");
Thread.Sleep(1010);
throw new Exception("1");
} finally {
Thread th = Thread.CurrentThread;
Console.WriteLine(
th.ManagedThreadId + " " +
th.IsThreadPoolThread);
}

}


というコードで試してみる。
あえて、tm.Interval よりも、em_Elapsed メソッドの方が時間がかかるようにしてある。

これを実行すると、今までのプログラムと違って、強制終了されない。
このコードを動かすと、当然だが、IsThreadPoolThread は、常に trueだ。
一方、ManagedThreadId は、4,5,6の値が何度も表示され、7以上の値が表示されることはない。

スレッド内で例外を処理しなくても、スレッドが自動的にスレッドプールに返却されているようだ。

さらに、興味深い?のは、AppDomain.UnhandledExceptionで例外がキャッチできないことだ。tm_Elapsed 内で未処理の例外があると、この例外は行方不明になってしまう。

これまでの結論は、AppDomain.UnhandledExceptionで は使えないってこと。


それと、繰り返しになるが、Timerの場合は、例外をキャッチしなくてもプログラムが強制終了してしまうことは無い。
一方、Threadの場合は、強制終了されてしまう。
この2つの違いは、スレッドプールと、通常のマニュアルスレッドの違いから来るのかな?
それとも、Timer独自の仕様なのだろうか?

ThreadPool.QueueUserWorkItem や DelegateのBeginInvoke についても調べないといけないな。


 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/50841095