views:

283

answers:

6

Hi
I want to pass an exception from current thread(that thread isn't main thread)to main thread.
Why?cuz I check my hard lock in another thread(that thread use timer for checking), and when HardLock is not accessible or invalid, I create an exception which is define by myself and then throw that exception.
So that exception don't work well ;(

+3  A: 

Knowing nothing else, it seems like your locking is broken, if you need a thread to ensure that your locks aren't held too long or are invalid.

If you really need to throw exceptions to your main thread, set up a communication queue from all your 'worker threads' to your 'master thread', and wrap your entire worker threads in an exception handler that does nothing more than append exceptions to the queue and then kills that thread. Your master thread can poll the queue to discover exceptions and restart threads that have died after correcting the error condition.

sarnold
so how do that you say!any sample
Rev
a good site describing threads and communicating between them is http://www.albahari.com/threading/
Patrick
thx for help! I will be read that
Rev
+2  A: 

Pass along a reference to the execution context of the main form to the thread (via the delegate or field). Then invoke a method (either send or post) via that synchronization context from your thread that throws the exception. The execution context will ensure it is processed by the ui thread.

MaLio
+8  A: 

Your best bet is to replace the Thread with a Task (new in .NET 4.0). The Task class handles proper marshaling of the exception to whatever thread checks the result of the task.

If using .NET 4.0 is not possible, then CoreEx.dll from the Rx extensions includes an Exception.PrepareForRethrow extension method that preserves the call stack for exceptions. You can use this in conjunction with MaLio's suggestion of SynchronizationContext to marshal an exception to another thread.

Stephen Cleary
Great Tip, I Mean 'Task'
Rev
+2  A: 

You might find it easier to keep the exception handling within the thread and pass back the exception message and stack trace by returning MyException.ToString() in a callback. When I get exceptions from another thread, everything I'm looking for is in that string.

ebpower
+1  A: 

Just my 2 cents.

I think you can use Invoke, BeginInvoke on the main form if you are running Windows Forms to send an exception there from try/catch block. Or you can create an event handler/delegate in a main thread and send exceptions through that to the main thread so the method in a main thread can process it. To be honest haven't tried those solutions but those are my first ideas.

PS. Maybe creating a WorkerQueue on the main thread is also an option. It will run as a backgroundWorker and when it gets new exception sent in it processes it accordingly... I can give you small examples on that if you're interested.

Edit:

public class JobQueue
{
    private Queue<Exception> pendingJobs = new Queue<Exception>();
    private Exception defaultJob = null;

    bool run = true;

    public void AddJob(Exception job)
    {
        pendingJobs.Enqueue(job);
    }

    public JobQueue()
    {
        defaultJob=null;
    }

    public void StopJobQueue()
    {
        run = false;
    }


    public void Run()
    {
        while (run)
        {

                Exception job = (pendingJobs.Count > 0) ? pendingJobs.Dequeue() : defaultJob;

                if (job!= null)
                {
                  ////what to do with current Exception
                 }

            Thread.Sleep(20); //I know this is bad...
        }


        pendingJobs.Clear();
    }



}
}

To use it: In your main thread class:

    private JobQueue m_jobQueue;

In Initialize() or wherever your main thread starts:

   Backgroundworker bw = new Backgroundworker();
   bw.DoWork+= jobQueue.Run;
   bw.StartAsync();
    //m_jobQueue = new JobQueue();
    //    new Thread(new ThreadStart(jobQueue.Run)).Start(); 

And to send an exception use:

   m_jobQueue.AddJob(StackOverflowException);

Stop by:

    m_jobQueue.StopJobQueue();
nomail
let see ur example!
Rev
I've edited my post so you can see it better.
nomail
thank great help
Rev
You never assign `defaultJob` (or am I missing something?), what is it for? A simple replacement for `Thread.Sleep` is to use the AutoResetEvent (even works on Windows Mobile). Create a new `AutoResetEvent`, do a `while (pendingJobs.Count > 0) { job = pendingJobs.Dequeue(); }`, in case a new job gets enqueued while dequeueing, inside your other while and put a `resetEvent.WaitOne` instead of Thread.Sleep. In `Enqueue` you could do a `resetEvent.Set()` to wake up the one in `Run()`.
Patrick
Hi Patrick! You are right. I just basically copied it out of my project with deleting most of the code for simplicity. My bad. But at least as an example I think it will do. Thanks for pointing out those points.
nomail
+2  A: 

You can use the exception as an parameter in event.
And handle it after sending the exception to other thread.
Code example.

public delegate void SendToMainDel(string threadName,Exception ex);
public event SendToMainDel SendToMainEv;

public void MySecondThread()
{
    try
    {
    ....
    }catch(Exception ex)
    {
         if(SendToMainEv!=null)
            SendToMainEv("MySecondThread",ex);
    }
}

...
    SendToMainEv += ReceiveOtherThreadExceptions;
...

public void ReceiveOtherThreadExceptions(string threadName,Exception ex)
{ 
   if(InvokeRequired)
   {
      BeginInvoke(new SendToMainDel(ReceiveOtherThreadExceptions), threadName, ex);
      return;
   }

   //there you can handle the exception
   //throw ex;
}
Avram