2011-03-14 68 views
3

ThreadA产生ThreadB。通知另一个异常的线程

ThreadB引发异常。

ThreadA如何知道这个异常?

using System; 
using System.Threading; 
namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      ThreadStart threadDelegate1 = new ThreadStart(MyClass1.DoThis); 
      Thread ThreadA = new Thread(threadDelegate1); 
      ThreadA.Start(); 
      Thread.Sleep(100000); // this thread is doing something else here, sleep simulates it 

     } 
    } 
    class MyClass1 
    { 
     public static void DoThis() 
     { 
      try 
      { 
       ThreadStart threadDelegate1 = new ThreadStart(MyClass2.DoThat); 
       Thread ThreadB = new Thread(threadDelegate1); 
       ThreadB.Start(); 
       Thread.Sleep(100000); // this thread is doing something else here, sleep simulates it 

      } 
      catch (Exception e) 
      { 
       // I want to know if something went wrong with MyClass2.DoThat 
      } 
     } 
    } 

    class MyClass2 
    { 
     public static void DoThat() 
     { 
      throw new Exception("From DoThat"); 
     } 
    } 
} 
+0

似乎是[这酮]重复(http://stackoverflow.com/questions/2810468/c-exception-handling-on-background-threads-使用线程池) – 2011-03-14 19:59:40

+0

不寻找python的例子:) – 2011-03-14 20:02:09

+0

你在两个编辑之间发现了这个评论:) – 2011-03-14 20:06:00

回答

0

这里有一种方法,使用的ManualResetEvent和lambda表达式:

 try 
     { 
      Exception exc; 
      using (ManualResetEvent resetEvent = new ManualResetEvent(false)) 
      { 
       Thread ThreadB = new Thread(() => 
       { 
       try 
       { 
        MyClass2.DoThat(); 
       } 
       catch (Exception e) 
       { 
        exc = e; 
        resetEvent.Set(); 
       } 
       }); 
       ThreadB.Start(); 
       if (resetEvent.WaitOne(10000)) 
       { 
       throw exc; 
       } 
      } 
     } 
     catch (Exception e) 
     { 
      // I want to know if something went wrong with MyClass2.DoThat 
     } 

你可以打扫一下,想必这取决于你想具体做什么。

0

只要你的线程在休眠,它就不能被另一个线程引起的异常中断。如果你可以控制你的线程如何做别的事情,他应该等待一个可以提醒的模式,等待一个threadExceptionEvent。 如果您无法控制线程在等待的方式,您可以做的最好的事情就是检查线程之间的时间。一个bool异常标志并抛出这个。

以下代码显示了如何一次等待几个WaitHandles,并根据正确触发事件做出反应。

using System; 
using System.Threading; 

class Program 
{ 
    static AutoResetEvent _ExceptionEvent = new AutoResetEvent(false); 
    static WaitHandle _SomeEvent = new AutoResetEvent(false); 
    static WaitHandle[] _Waiters = new WaitHandle[] { _ExceptionEvent, _SomeEvent }; 
    static Exception _LastThrownException = null; 

    static int _CatchedExCount = 0; 
    static void ThreadA() 
    { 
     while (true) 
     { 
      int eventIdx = WaitHandle.WaitAny(_Waiters); 
      if (eventIdx == 0) // Exception event 
      { 
       Exception lastEx = Interlocked.Exchange(ref _LastThrownException, null); 
       if (lastEx != null) 
       { 
        Console.WriteLine("Thread A got exception {0}", lastEx.Message); 
        _CatchedExCount++; 
        //throw lastEx; 
       } 
      } 
     } 

    } 

    static void ThreadB() 
    { 
     while (true) 
     { 
      try 
      { 
       ThreadBWorker(); 
      } 
      catch (Exception ex) 
      { 
       // Do not overwrite a pending exception until it was processed 
       Exception old = null; 
       do 
       { 
        old = Interlocked.CompareExchange(ref _LastThrownException, ex, null); 
        if(old != null) // wait a bit to allow processing of existing exception 
        { 
         Thread.Sleep(1); 
        } 
       } 
       while (old != null); 
       _ExceptionEvent.Set(); 
      } 
     } 
    } 

    static int _exCount = 0; 
    static void ThreadBWorker() 
    { 
     throw new Exception("Thread B Exception " + _exCount++); 
    } 

    static void Main(string[] args) 
    { 
     Thread t2 = new Thread(ThreadB); 
     t2.Start(); // start producing exception 

     Thread t1 = new Thread(ThreadA); 
     t1.Start(); // wait for exceptions 
    } 
} 

此致, 阿洛伊斯克劳斯