2009-04-22 11 views
13

私はなぜ考えているのですか?誰かが、スレッド内で発生した例外が、それを開始したコードによって決して捕捉されない理由をよく把握しているかどうか尋ねたいと思います。ここで私が言いたいことを証明するためにいくつかの非常に単純なコードは次のとおりです。試してみる/キャッチとスレッディング

using System; 
using System.Collections.Generic; 
using System.Threading; 

namespace TestCrash 
{ 
    class Program 
    { 
     private static void Crash(object control) 
     { 
      AutoResetEvent are = (AutoResetEvent)(((object[])control)[0]); 
      are.Set(); 
      throw new Exception("Burn baby burn"); 
     } 
     static void Main(string[] args) 
     { 
      try 
      { 
       List<WaitHandle> waitHandles = new List<WaitHandle>(); 
       for (int i = 0; i < 100; i++) 
       { 
        AutoResetEvent are = new AutoResetEvent(false); 
        waitHandles.Add(are); 
        object[] procControl = new object[] { are }; 
        ThreadPool.QueueUserWorkItem(Crash, procControl); 
        WaitHandle.WaitAll(waitHandles.ToArray()); 
       } 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.Message); 
      } 
     } 
    } 
} 

(それがクラッシュし、私は単純のtry/catchを持っていることによって、私は安全だろうと思ったが、私はそれが当てはまらないというハードな方法を発見しました私のサービスの一つ)。

+0

奇妙なことに、まさに今でも同様のスレッドを開始しようとしていました。 –

+0

私は、例外が呼び出しスレッドにバブルアップしていることを確認しました。 AlthoはThreadPoolを使用していません。スレッドの新規スレッド(新しいThreadStart(delegate(){Console.WriteLine( "Crash!"); DoCrashyThingy();})); T.Start(); – Fusspawn

+0

私は簡単にそれについて間違っている可能性があります、私の仕事のほとんどはこの恐ろしいシングルスレッドbehemoth .. – Fusspawn

答えて

28

一般的に、新しいスレッドで例外がスローされる時点で、元のスレッドがどこにあるのかわかりません。なぜ、スレッドが例外をスローするのを待っていますか?

関連するスタックを考えます。例外がスローされると、スタックは適切なキャッチブロックに到達するまでスタックを上がります。新しいスレッドは、作成するスレッドとは完全に別のスタックを持ちます。したがって、作成するスレッドのスタックのcatchブロックに到達することはありません。

編集:作成するスレッドになったときに、Windowsフォームアプリケーションのメッセージループのように他のことが起こるのを待つようにシステムを設計できます。新しいスレッドは例外をキャッチしてメッセージを作成スレッドに送信することができ、例外を処理することができます。それは普通の設定ではありません - あなたはすべて明示的にそれを行う必要があります。

+0

ありがとう、ジョン。私が困惑したのは、実際に親プロセスをクラッシュさせたことでした。私はスレッドが少なくともすべてを落とすのではなく、平和的に死ぬべきだと思っています。 –

+0

いいえ、ポイントは、予期しない例外が深刻な間違っていることを示している可能性があり、失敗することは一般的にはより良い考えです。これは.NET 2.0の新しい動作です。 http://msdn.microsoft.com/en-us/library/ms228965.aspx –

+0

を参照してください。スレッドキューにキューイングされるコードブロックは、try/catchブロック自体に完全に囲まれている必要があります。ベストプラクティスですか?私は、スレッドの1つが問題になったために降りたくないサービスを持っています... –

2

特に、複数のスレッドが関わっている場合(古い言葉を知っている)、仮定を立てることは悪い考えです。

なぜになるのですか?スレッドを開始したコードは例外を参照してください。例外がスローされたときにスレッドを開始したコードが存在しないこともあります。

+1

私は生き残るために前提が必要であるという現実を無視しているので、私はそれを嫌う。その言葉は、あなたの仮定が何であるかを理解し、それらが間違っている場所を特定することを指すべきである。 –

2

実行中のスレッドは、別のスレッドで実行されているため、try/catch文でキャッチされません。 Try/Catchは、現在のスレッドに対してのみ機能します。あなたがする必要があるのは、スレッドによって実行されている関数をtry/catchし、そのクラッシュが発生したときに何が起こるかを管理する何らかの方法があることです。

2

EventGeneratingThread wrapperを使用すると、スレッドを生成したプロセスからスローされた例外を捕捉して処理できます。あなたはこれでそれらを期待するように私は、バックグラウンドワーカーを使用して、そして私のループ作業中のすべてのトライキャッチしていますあなたのDoWorkサブ

<System.Diagnostics.DebuggerNonUserCodeAttribute()> _ 

前にこれを追加すること

2

してみてください。

関連する問題