簡體   English   中英

從線程向主線程發送異常?

[英]Sending an exception from thread to main thread?

我想將當前線程(該線程不是主線程)的異常傳遞給主線程。 為什么? 因為我在另一個線程中檢查我的硬鎖(該線程使用計時器進行檢查),並且當HardLock不可訪問或無效時,我創建了一個由我自己定義的異常,然后拋出該異常。
所以異常不能很好地運作。

最好的辦法是用一個Task替換Thread (.NET 4.0中的新增功能)。 Task類處理異常的封送處理,無論什么線程檢查任務的結果。

如果無法使用.NET 4.0,則Rx擴展中的 CoreEx.dll包含Exception.PrepareForRethrow擴展方法,該方法保留Exception.PrepareForRethrow的調用堆棧。 您可以將此與MaLio的SynchronizationContext建議結合使用,以便將異常編組到另一個線程。

您可以將異常用作事件中的參數。
並在將異常發送到其他線程后處理它。
代碼示例。

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

如果你需要一個線程來確保你的鎖沒有太久或者無效,那么看起來你的鎖定就好了。

如果您確實需要向主線程拋出異常,請設置從所有“工作線程”到“主線程”的通信隊列,並將整個工作線程包裝在異常處理程序中,該處理程序除了將異常附加到隊列,然后殺死該線程。 主線程可以輪詢隊列以發現異常並重新啟動糾正錯誤情況后已經死亡的線程。

將對主窗體的執行上下文的引用傳遞給線程(通過委托或字段)。 然后從引發異常的線程通過該同步上下文調用方法(發送或發布)。 執行上下文將確保它由ui線程處理。

您可能會發現在線程中保持異常處理更容易,並通過在回調中返回MyException.ToString()來傳回異常消息和堆棧跟蹤。 當我從另一個線程獲得異常時,我正在尋找的所有內容都在該字符串中。

只需2美分。

如果您運行Windows窗體以從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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM