簡體   English   中英

WPF中的線程異常中止

[英]Thread abort exception in WPF

我正在嘗試在WPF應用程序中實現加載程序。 在執行一些繁重的操作期間,UI線程被凍結,因此我不得不使用線程來實現加載程序。 每次加載程序加載時,都會創建一個新線程,並且在加載程序啟動時該線程將被中止(手動)。 我面臨的問題是,有時應用程序會崩潰,給出ThreadAbortException

這是啟動加載程序的代碼:

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

您應該在線程中添加一個try catch塊,該塊可能引發異常並根據需要對其進行管理。

無論如何,就像@Josh在其他類似文章中所說的那樣

有很多更好的方法可以在不使用Thread.Abort的情況下中止線程,它不僅會在無法預測的位置混亂地中斷代碼,而且還不能保證正常工作,因為如果您的線程當前正在調用某些非托管代碼,則該線程不會中止直到控制權返回到托管代碼。

最好使用某種類型的同步原語,例如aManualResetEvent作為標記,告訴您的線程何時退出。 您甚至可以為此使用一個布爾字段,這是BackgroundWorker所做的。

如果您為自己拋出異常,請忘記Thread.Abort 這就是為什么:

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

取而代之的是,向您的加載器發送取消請求(可以是一個簡單的bool ),您應該在加載操作期間定期輪詢該取消請求。 是一個示例,如何使用BackgroundWorker和volatile字段來實現。

暫無
暫無

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

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