从线程向主线程发送异常?

时间:2010-08-04 07:39:37

标签: c# multithreading exception exception-handling

我想将当前线程(该线程不是主线程)的异常传递给主线程。 为什么?因为我检查了另一个线程中的硬锁(该线程使用计时器进行检查),并且当HardLock无法访问或无效时,我创建了一个由我自己定义的异常然后抛出该异常。
所以异常不能很好地运作。 ;(

6 个答案:

答案 0 :(得分:13)

最好的办法是用Thread(.NET 4.0中的新增功能)替换TaskTask类处理任何线程检查任务结果的异常编组。

如果无法使用.NET 4.0,则Rx extensions中的CoreEx.dll包含Exception.PrepareForRethrow扩展方法,该方法会保留调用堆栈以查找异常。您可以将此与MaLio的SynchronizationContext建议结合使用,以便将另一个线程的异常编组。

答案 1 :(得分:4)

您可以将例外用作事件中的参数 并在将异常发送到其他线程后处理它 代码示例。

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

答案 2 :(得分:3)

知道其他任何事情,如果您需要一个线程来确保您的锁定时间不长或无效,那么您的锁定似乎已被破坏。

如果确实需要向主线程抛出异常,请设置从所有“工作线程”到“主线程”的通信队列,并将整个工作线程包装在异常处理程序中,该处理程序只执行附加操作队列的异常,然后杀死该线程。您的主线程可以轮询队列以发现异常并重新启动在纠正错误条件后已经死亡的线程。

答案 3 :(得分:2)

将对主窗体的执行上下文的引用传递给线程(通过委托或字段)。然后从引发异常的线程通过该同步上下文调用方法(发送或发布)。执行上下文将确保它由ui线程处理。

答案 4 :(得分:2)

您可能会发现在线程中保持异常处理更容易,并通过在回调中返回MyException.ToString()来传回异常消息和堆栈跟踪。当我从另一个线程获得异常时,我正在寻找的所有内容都在该字符串中。

答案 5 :(得分:2)

只需2美分。

我认为如果你运行Windows Forms从try / catch块发送异常,你可以在主窗体上使用Invoke,BeginInvoke。或者,您可以在主线程中创建事件处理程序/委托,并通过该线程将异常发送到主线程,以便主线程中的方法可以处理它。说实话,没有尝试过那些解决方案,但这些是我的第一个想法。

PS。也许在主线程上创建一个WorkerQueue也是一种选择。它将作为backgroundWorker运行,当它发送新的异常时,它会相应地处理它...如果你感兴趣,我可以给你一些小例子。

编辑:

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



}
}

使用它: 在主线程类中:

    private JobQueue m_jobQueue;

在Initialize()或主线程开始的任何地方:

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

并发送例外使用:

   m_jobQueue.AddJob(StackOverflowException);

停止:

    m_jobQueue.StopJobQueue();