开发者

Sending an exception from thread to main thread?

开发者 https://www.devze.com 2023-01-10 07:47 出处:网络
I want to pass an ex开发者_运维百科ception from current thread (that thread isn\'t main thread)to main thread.

I want to pass an ex开发者_运维百科ception from current thread (that thread isn't main thread)to main thread. Why? Because 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 defined by myself and then throw that exception.

So that exception doesn't work well. ;(


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.


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


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.


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.


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.


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();
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号