2012-01-08 7 views
8

スレッド内でスローされた例外は、通常、別のスレッドで捕捉できなかったという事実に精通しています。 どうすればエラーをメインスレッドに転送できますか?cのメインスレッドに例外を明示的に渡す方法#

public static void Main() 
{ 
    new Thread (Go).Start(); 
} 

static void Go() 
{ 
    try 
    { 
    // ... 
    throw null; // The NullReferenceException will get caught below 
    // ... 
    } 
    catch (Exception ex) 
    { 
    // Typically log the exception, and/or signal another thread 
    // that we've come unstuck 
    // ... 
    } 
} 

答えて

6

あなたの例では、コンソールアプリケーションであれば、自分のメインメソッドが終了します...

Tasksでこれを行うには良い方法がある.NET 4を使用していますが、Threadsを使用する必要があると仮定している場合おそらくGoが実行を開始する前に。したがって、例外がスローされたときにあなたの「メインスレッド」が存在しない可能性があります。これをやめるには、同期が必要です。このような

何かが行う必要があります。

static Exception _ThreadException = null; 

public static void Main() 
{ 
    var t = new Thread (Go); 
    t.Start(); 

    // this blocks this thread until the worker thread completes 
    t.Join(); 

    // now see if there was an exception 
    if (_ThreadException != null) HandleException(_ThreadException); 
} 

static void HandleException(Exception ex) 
{ 
    // this will be run on the main thread 
} 

static void Go() 
{ 
    try 
    { 
     // ... 
     throw null; // The NullReferenceException will get caught below 
     // ... 
    } 
    catch (Exception ex) 
    { 
     _ThreadException = ex; 
    } 
} 

を、これはUIアプリであれば、物事は少し簡単です。 UIスレッドの参照をGoメソッドに渡す必要がありますので、例外をどこに送信するのかが分かります。これを行う最善の方法は、UIスレッドのSynchronizationContextを渡すことです。

このような何かが働くだろう:

public static void Main() 
{ 
    var ui = SynchronizationContext.Current; 
    new Thread (() => Go(ui)).Start(); 
} 

static void HandleException(Exception ex) 
{ 
    // this will be run on the UI thread 
} 

static void Go(SynchronizationContext ui) 
{ 
    try 
    { 
     // ... 
     throw null; // The NullReferenceException will get caught below 
     // ... 
    } 
    catch (Exception ex) 
    { 
     ui.Send(state => HandleException(ex), null); 
    } 
} 
7

C#4.0の場合は、あなたの代わりにThreadTaskを使用することができ、利用することができます。 Taskのキャッチされていない例外は、自動的に結合スレッドに伝播されます。このルールの例と例外については、http://msdn.microsoft.com/en-us/library/dd997415.aspxを参照してください。

+0

C#4.0が利用できない最小限の例です。 – user829174

0

"メインスレッド"と呼ばれ、例外をポーリングするか、例外を待つと仮定します。これはキューとセマフォで行うことができます。

catch(Exception ex) 
{ 
    lock(queueLock) 
    { 
     queue.Enqueue(ex) 
     semaphore.Release(); 
    } 

} 

メインスレッドでは、セマフォをポーリングまたは待機することができます。

2

これは本当に古いスレッドですが、私はこの問題に対する独自のアプローチをとっていますので、ここで解決策を説明します。

私の場合の主な目標は、メインスレッドが、他の応答で提案されているように監視または待機するのではなく、子スレッドが例外を取得した瞬間に例外によって中断されることでした。 他のスレッドで述べたように、従来の方法ではできませんが、他のスレッドからメインスレッドに割り込みを送ることができます。

メインスレッドに割り込みを送信すると、メインスレッドでThreadInterruptedExceptionが生成されます。メインスレッドでそれをキャッチし、他のスレッドによって生成されたフラグをチェックすると、例外の詳細も転送されます。ここで

は(あなたがクラスにそれを破ると、後に優れた設計を行うことができます)

static void Main(string[] args) 
    { 


     // initialize the second thread *************************** 
     Exception exFromThread = null; 

     Thread thread = new Thread((mainThread) => 
     { 
      Thread.Sleep(1000); 
      exFromThread = new Exception("Exception from other thread"); 
      ((Thread)mainThread).Interrupt(); // makes the main thread get exception 
     }); 

     thread.Start(Thread.CurrentThread); 
     // ******************************************************** 

     try 
     { 
      // This loop represents your main thread logic 
      for (int i = 0; true; i++) 
      { 
       Thread.Sleep(500); 
       Console.WriteLine("main thread logic: " + i); 
      } 
     } 
     catch (ThreadInterruptedException ex) 
     { 
      Console.WriteLine("Thread have been interrupted"); 
      Console.WriteLine(exFromThread.Message); 
     } 

     Console.WriteLine("Press any key.."); 

     Console.ReadLine(); 
    } 
関連する問題