代码之家  ›  专栏  ›  技术社区  ›  Rev

将异常从线程发送到主线程?

  •  14
  • Rev  · 技术社区  · 14 年前

    我想将一个异常从当前线程(该线程不是主线程)传递到主线程。 为什么?因为我在另一个线程中检查我的硬锁(该线程使用计时器进行检查),以及何时 HardLock 不可访问或无效,我创建一个由我自己定义的异常,然后抛出该异常。
    所以这个例外不起作用(

    6 回复  |  直到 9 年前
        1
  •  13
  •   Stephen Cleary    13 年前

    你最好的办法是更换 Thread 用一个 Task (在.NET 4.0中新增)。这个 任务 类处理异常到检查任务结果的任何线程的正确封送处理。

    如果无法使用.NET 4.0,则从 Rx extensions 包括 Exception.PrepareForRethrow 为异常保留调用堆栈的扩展方法。你可以把这个和马里奥的建议结合起来使用 SynchronizationContext 将异常封送到另一个线程。

        2
  •  4
  •   Avram    14 年前

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

    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;
    }
    
        3
  •  3
  •   sarnold    14 年前

    如果您需要一个线程来确保您的锁不会被持有太长时间或无效,那么您的锁似乎被破坏了。

        4
  •  2
  •   MaLio    14 年前

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

        5
  •  2
  •   Ed Power    14 年前

    您可能会发现,将异常处理保留在线程中,并通过返回 MyException.ToString() 在回拨中。当我从另一个线程获取异常时,我要查找的所有内容都在该字符串中。

        6
  •  2
  •   nomail    14 年前

    就我的2美分。

    另外,在主线程上创建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();