天天看點

.NET 4.0裡異常處理的新機制

前幾天,有一個朋友問我為什麼在.NET裡不能捕捉(catch)到一些異常了,而且在調試器裡也捕捉不到。研究了一下,是.NET 4.0裡新的異常處理機制搗的鬼。

在.NET 4.0之後,CLR将會差別出一些異常(都是SEH異常),将這些異常辨別為破壞性異常(Corrupted State Exception)。針對這些異常,CLR的catch塊不會捕捉這些異常,即使你用類似下面的代碼:

            try

            {

                TestMethod();

            }

            catch (Exception e)

                Console.WriteLine("Catching exception: {0}", e);

是以在4.0以後,大部分SEH(我懷疑是所有)異常都被辨別成破壞性異常,在.NET裡,預設情況下CLR不會捕捉它們,而是任由作業系統來處理—即關閉程式,并打開一個錯誤對話框通知使用者。為了保證相容性,在4.0以前編譯的程式,例如在2.0、3.0和3.5編譯的程式,依然采用的是老的政策—即.NET會同時捕捉.NET異常和SEH異常。而在4.0下面編譯的程式才會使用新的政策,這也是在文章的開頭,我的朋友所碰到的問題。你可以在.NET 4.0下面編譯下面的程式,體驗一下這個新變化:

Program.cs:

Ref.cpp:

上面的代碼裡,Program.cs使用P/Invoke技術調用了Ref.dll檔案裡的TestMethod,但是TestMethod嘗試給一個空指針指派,導緻一個AccessViolation異常。如果你在2.0下面編譯program.cs,并執行的話,這個AccessViolation異常會被catch(Exception e)捕捉到,而如果你在4.0下面編譯并執行的話,你會發現catch (Exception e)是不能捕捉到這個異常的。

然而并不是所有人都想要這個新的異常機制,如果你的程式是在4.0下面編譯并運作,而你又想在.NET程式裡捕捉到SEH異常的話,有兩個方案可以嘗試:

1.         在托管程式的.config檔案裡,啟用legacyCorruptedStateExceptionsPolicy這個屬性,即簡化的.config檔案類似下面的檔案:

App.config:

<?xml version="1.0"?>

<configuration>

 <startup>

   <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>

 </startup>

    <runtime>

      <legacyCorruptedStateExceptionsPolicy enabled="true" />

    </runtime>

</configuration>

這個設定告訴CLR 4.0,整個.NET程式都要使用老的異常捕捉機制。

2.         在需要捕捉破壞性異常的函數外面加一個HandleProcessCorruptedStateExceptions屬性,這個屬性隻控制一個函數,對托管程式的其他函數沒有影響,例如:

你也可以下載下傳示例代碼自己試一下(需要VS 2010才能編譯):

<a href="http://files.cnblogs.com/killmyday/CSEsample.zip">/Files/killmyday/CSEsample.zip</a>

本文轉自 donjuan 部落格園部落格,原文連結: http://www.cnblogs.com/killmyday/archive/2010/09/05/1818533.html  ,如需轉載請自行聯系原作者