线程通知另一个例外

时间:2011-03-14 19:56:03

标签: c# multithreading

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");
        }
    }
}

2 个答案:

答案 0 :(得分:0)

这是一种方法,使用ManualResetEvent和lambdas:

        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
        }

你可以清理它,当然取决于你想要做什么。

答案 1 :(得分: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
    }
}

此致,    Alois Kraus