2013-04-12 79 views
21

我已閱讀文章ASP.NET application pool shutdown problemIIS 7.5: problem with Application pool但他們沒有回答我的問題。爲什麼我的IIS7應用程序池在從ASP.NET頁面調用的DLL中的異常之後關閉?

我有一個C#ASP.NET頁面,在代碼實現中,通過BIN目錄提供的DLL實例化一個類,然後在這個實例上調用一個方法。由於DataRow對象中不存在列,因此DLL中的方法會拋出System.ArgumentException。事件日誌顯示以下錯誤:

Source: ASP.NET 2.0.50727.0 
Application ID: /LM/W3SVC/1/ROOT/... 
Process ID: 9476 
Exception: System.ArgumentException 
Message: Column 'someColumn' does not belong to table. 
StrackTrace: 

在ASP.NET頁面調用代碼封裝在一個通用的try-catch塊的方法調用。當我請求頁面時,這會崩潰我的IIS實例的相應應用程序池,並且我的網站不再可用(錯誤503)。我手動必須重新啓動應用程序池,並再次工作。

更新 作爲要求try catch塊從背後的ASP.NET代碼:

try 
{ 
    SomeExternalClass someExternalClass = new SomeExternalClass(); 
    someExternalClass.SomeMethod(someId); 
} 
catch(Exception ex) 
{ 
    // "smp" is an instance of "StatusMessagePanel", a control we use on all pages 
    // to show error information, basically a div container with an icon. 
    smp.ShowError(ex.Message); 
} 

現在我的問題是,爲什麼一個相對「簡單」的例外,如試圖訪問時System.ArgumentException被拋出不存在DataRow列,崩潰整個網站? ASP.NET頁面的通用塊try-catch也沒有幫助,這也不應該是完全使整個網站不可用的原因,或者這是一個錯誤的假設?我從來沒有想過,這基本上可以把(II)服務器關閉。

預期人們告訴我,我應該檢查列存在之前,我訪問他們:我知道這一點,遺留代碼現在已經改變,但這不是我的問題,如上所述,我想知道爲什麼後果如此激烈。

更新2

問題的方法被調用的DLL裏面會啓動裹在try-catch阻塞線程:

[...] 
try 
{ 
    ThreadStart starter =() => CreateReport(...) 
    Thread thread = new Thread(starter); 
    thread.Start(); 
    if(!thread.Join(TimeSpan.FromMinutes(15))) 
    { 
     // Log some timeout warning 
    } 
    else 
    { 
     // Log information about successful report generation 
    } 
} 
catch(Exception ex) 
{ 
    // Log error information 
} 
+0

在catch塊會發生什麼?如果拋出異常,你可能會遇到麻煩。你可以發佈try catch代碼嗎? – levelnis

+0

catch塊調用一個方法,使客戶端(瀏覽器)可見錯誤消息,我會更新我的問題。 – Gorgsenegger

+0

只是爲了幽默我 - 如果你完全刪除try-catch塊並且只是調用方法,應用程序池是否仍然崩潰? – levelnis

回答

19

最有可能您的應用程序池被IIS's Rapid Fail Protection功能自動關閉,如鏈接問題中所述。如果您檢查您的事件日誌,可能會有多個未處理的異常快速連續拋出。

簡單地說,在一個可配置時間足夠未處理的異常(默認值是5的5分鐘),將關閉該程序池,造成503服務不可用響應。

這背後有其理由是,如果你有一個錯誤的應用程序,你可能不希望它在每個後續請求自動重新啓動,消耗資源,並可能損壞數據。

我不得不承認,這是不是「默認」的行爲,我想要麼預期。

退房Rick Stahls explanation,這是多一點深入。

要真正解決這個問題,需要從被拋出捕獲異常,或防止異常(如@leppie建議)。未處理的異常應該拆除整個執行過程(意味着單個請求/工作進程,而不是IIS) - 它使得.Net代碼更容易調試,因爲它不會隱藏錯誤或者簡單地掛起應用程序。

請注意,這是在NET 2.0改爲:
http://msdn.microsoft.com/en-us/library/ms228965.aspx
http://support.microsoft.com/kb/911816

更新
此基礎上您的更新,我不認爲你的例外,實際上是抓住了,如果拋出從CreateReport()。這種方法在一個單獨的線程執行:

exception still thrown

你需要一個try-catch中的CreateReport()體內如果沒有一個已經:

public static void CreateReport() { 
    try { 
     throw new Exception("reducto"); 
    } catch { 
     Console.WriteLine("done did."); 
    } 
} 
+0

感謝您提供更詳細的信息,儘管我仍然不明白爲什麼在DLL中捕獲的異常*會導致應用程序池關閉。在快速連續拋出多個異常的情況下也不應該如此,因爲DLL的方法的執行在拋出第一個異常時終止。事件日誌還顯示只生成一個異常。 – Gorgsenegger

+0

@Gorgsenegger根據您的反饋更新了答案 –

+0

謝謝,我會盡快驗證時間 - 我們只是將我們的TFS移動到不同的網絡,並且仍然處於正在加速的過程中,非常抱歉,請延遲幾天。 – Gorgsenegger

4

它發生在我一次。真正的錯誤(在我的情況下)是關閉池的堆棧溢出。

看起來IIS似乎在保護自己免於消耗太多資源。

我發現使用DebugDiag的問題。

這裏是我開始:http://www.webdebug.net/index.php/2012/12/collect-iis-crash-dump-with-debugdiag/

I'd like to understand why an exception in an external DLL can cause the IIS application pool to shutdown, even if the exception is being caught inside the DLL and also when calling the DLL's method from within the code behind of the ASP.NET page.

外部DLL還會在您的應用程序池中運行。這個DLL中的重大崩潰也會導致應用程序池崩潰。一些異常不能被處理,並且stackoverflow異常就是其中之一。主題討論here。也許這是你的情況。

相關問題