thread notifying another thead of an exception
ThreadA spawns ThreadB.
ThreadB throws an exception.
How can ThreadA know about this exception?
using System;
using System.Threading;
namespa开发者_如何学Pythonce 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");
}
}
}
Here is one way, using ManualResetEvent and 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
}
You can clean this up, surely depending on what you want to do specifically.
As long as your thread is sleeping it cannot be interrupted by an exception caused by another thread. If you can control how your thread is doing something else he should be waiting in an alertable mode where the does e.g. wait for a threadExceptionEvent. If you do not have control how your thread is waiting the best thing you can do is to check in the times between your thread did something for e.g. a bool exception flag and throw this one.
The following code shows how you can wait for several WaitHandles at once and react depending on the fired event appropriately.
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
}
}
Yours, Alois Kraus
精彩评论