2016-04-22 134 views
0

我想在我的WPF應用程序中實現裝載器。在一些繁重的操作中,UI線程被凍結,所以我必須使用線程來實現加載器。每次加載器加載時,都會創建一個新線程,並且在加載器啓動時該線程會中止(手動)。我面臨的問題是,有時應用程序崩潰給出ThreadAbortExceptionWPF中的線程異常終止

這是啓動加載器代碼:

try 
     { 
      //if(newWindowThread !=null && !newWindowThread.IsAlive) { } 
      newWindowThread = new Thread(new ThreadStart(() => 
      { 
       try 
       { 
        // Create and show the Window 
        awq = new BusyIndicatorDisguise(BusyMessage); 
        awq.Show(); // <== POINT WHERE THE EXCEPTION IS THROWN 
        //Start the Dispatcher Processing 
        if (!isDispatcherStarted) 
        { 
         var a = Thread.CurrentThread; 
         var b = Dispatcher.CurrentDispatcher; 
         //isDispatcherStarted = true; 
         Dispatcher.Run(); 
        } 

       } 
       catch (ThreadAbortException thEx) 
       { 

       } 
       catch (Exception ex) 
       { 

       } 
      } 
      )); 
      // Set the apartment state 
      newWindowThread.SetApartmentState(ApartmentState.STA); 
      // Make the thread a background thread 
      newWindowThread.IsBackground = true; 
      // Start the thread 
      newWindowThread.Start(); 
     } 
     catch (Exception ex) 
     { 

     } 

此代碼是用於停止裝載機:

if (newWindowThread != null && newWindowThread.IsAlive) 
     {   
      newWindowThread.Abort();    
     } 

我不能夠趕上這個例外在我的catch塊。也許是因爲它在不同的線程上。 我想知道如何避免ThreadAbortException

+0

考慮使用CancellationToken而不是中止線程。 – yaakov

回答

1

您應該在線程中添加一個try catch塊,以便根據您的需要拋出異常並對其進行管理。

無論如何,@Josh在其他類似的帖子說

有中止線程不使用Thread.Abort的不僅混亂在 不可預測的點打斷你的代碼 的更好的方法,這也是不保證工作,因爲如果 您的線程當前正在調用某些非託管代碼,則 線程將不會中止,直到控制返回到託管代碼。

使用某種類型的同步原語(如 aManualResetEvent)充當標誌,告訴您的線程何時退出,這會更好。 您甚至可以爲此使用布爾型字段,這是BackgroundWorker所做的。

+0

我已經在我的線程中放了一個try catch塊。無論如何,我之前沒有聽說過** ManualResetEvent **。將試一試,並會讓你知道。 –

1

如果您爲自己拋出異常,則忘記Thread.Abort。這就是爲什麼:

  • 拋出異常是一個非常昂貴的操作。它可以保存整個調用堆棧和其他有用的數據以進行調試。在這種情況下,你只需要設置一個簡單的標誌。
  • ThreadAbortException是一個棘手的問題。除非您在catch塊中調用Thread.ResetAbort,否則它會自動重新拋出異常處理程序塊的末尾。但不是這樣做
  • A ThreadAbortException是一個異步異常,這意味着它可以發生在您的代碼的任何一點,這可能會導致不可預知的結果。這是一個蠻力工具,例如任務管理器中的結束任務按鈕。只有當您不能重寫已執行的代碼(第三方組件)並且您確定可以卸載不穩定執行環境的剩餘部分(它在AppDomain中執行)時才使用它。

取而代之,請向您的加載程序發送取消請求(可以是簡單的bool),您應該在加載操作期間定期輪詢。 Here是一個示例,您可以通過使用BackgroundWorker和易失性字段來完成此操作。