簡體   English   中英

在線程中捕獲System.Exception

[英]Catching System.Exception in thread

我知道,除非在應用程序的頂層,否則捕獲System.Exception並不是一個好習慣。 那線程呢? 在線程的頂層捕獲System.Exception可以嗎?

更新:該線程是一個長期運行的線程,僅應在應用程序停止時終止。 因此,為了確保應用程序不會崩潰,我只需捕獲System.Exception並記錄錯誤。 一切都重新創建。

        while (Terminate == false)
        {
            var discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());

            try
            {
                var criteria = new FindCriteria(typeof(T));
                criteria.Scopes.Add(new Uri(Scope));
                var discovered = discoveryClient.Find(criteria);
                discoveryClient.Close();
                discoveryClient = null;

                // do something with the endpoints
            }
            catch (OutOfMemoryException e)
            {
                m_Logger.LogException(e, "Exception when trying to discover clients (Contract: {0})", typeof(T).Name);
                throw;
            }
            catch (Exception e)
            {
                m_Logger.LogException(e, "Exception when trying to discover clients (Contract: {0})", typeof(T).Name);

                if (discoveryClient != null)
                    (discoveryClient as IDisposable).Dispose();
            }

        }

這取決於線程正在執行的操作以及應用程序中線程的上下文。 一般來說,您應該遵循經驗法則: 除非您知道如何處理異常,否則不要捕獲異常 (我正在簡化,但這是經驗法則)。

由於我們在談論System.Exception而不是某些子類,因此我假設您實際上並不知道如何處理該異常。 記錄錯誤,並讓應用程序終止(唯一正當理由趕你不能處理的除外) 可以做到在不脫離提出它的線程內捕捉異常,所以簡單的答案是否定的,這是沒有確定

如果我沒有記錯的話,.NET 1實際上捕獲並吞噬了后台線程引發的所有異常。 這導致在寫的不好的程序這么多的問題,MS改變行為在.NET 2讓異常崩潰的應用程序-你能想象他們有很好的理由作出這樣的重大更改。

關於BackgroundWorker更新:

請不要將BackgroundWorker的使用模式誤認為是“吞下System.Exception是可以的”。 這是BackgroundWorker.RunWorkerCompleted的文檔所說的:

在訪問RunWorkerCompletedEventArgs.Result屬性之前,您的RunWorkerCompleted事件處理程序應始終檢查AsyncCompletedEventArgs.Error和AsyncCompletedEventArgs.Cancelled屬性。 如果引發了異常或操作被取消,則訪問RunWorkerCompletedEventArgs.Result屬性將引發異常。

簡單地說, 選擇忽略此建議或故意忽略返回值 (否則仍會引發異常!)是不好的編程習慣。

是的-這是個好主意:)

嗯,我看不出為什么有人建議捕獲頂級異常不是一個好主意。 說真的,你沒抓住他們嗎?

從實際的日常開發角度來看,如果您的后台線程有頂級異常,則您想了解一下。 您不希望應用程序崩潰,這是默認行為-令人驚訝的是,用戶不喜歡該應用程序。 這是您肯定想捕獲異常並記錄/恢復的少數幾個地方之一。

從官方上講,這不是一個好習慣,但有時確實可以做到。

參數與在“主”線程上執行此操作的參數完全相同。

一個主要的問題是,如果您吞下了這樣的錯誤,則您的應用程序可能會非常不正確地運行-例如,它可能會覆蓋關鍵的用戶數據-而不是終止。


如果您確實選擇了這條路線,則可能要小心,將ThreadAbortException從捕獲中排除-如果有人中止了工作線程,則這是“預期的異常”(在您的應用程序中可能是,也可能不是)

只處理異常,您可以做一些事情。 為了不顯示黃色屏幕,我個人更喜歡在global.asax事件Application_error中捕獲不必要的異常

通常,我們不打算直接創建新線程。 僅在少數情況下可以接受。

因此,如果確實在UI中使用new Thread() ,那將是令人頭疼的。

鼓勵使用BackgroundWorkerTask<T>封裝線程異常處理,因此就catch塊而言無需進行異常處理。


如果您想要自己的線程(從CLR通過C# ),這是四種可接受的情況:

我強烈建議您盡可能使用線程池執行異步計算綁定操作。 但是,在某些情況下,您可能想顯式創建專門用於執行特定計算綁定操作的線程。 通常,如果要執行要求線程處於線程池線程不正常的特定狀態的代碼,則需要創建一個專用線程。 例如,如果我希望線程以特殊優先級運行(所有線程池線程均以正常優先級運行,並且您不應更改線程池線程的優先級),則可以創建一個專用線程。 如果我想使該線程成為前台線程(所有線程池線程均為后台線程),我也將考慮創建和使用自己的線程,從而防止應用程序在線程完成其任務之前死亡。 如果計算綁定任務非常長時間運行,我還將使用專用線程。 這樣,當線程池試圖找出是否要創建一個額外的線程時,我就不會對線程池的邏輯費勁。 最后,如果我想啟動一個線程並可能通過調用Thread的Abort方法(在第21章“ CLR托管和AppDomains”中討論)過早中止該線程,則將使用專用線程。

暫無
暫無

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

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