其實,當你使用 Response.End 方法時,會因為內部呼叫 Thread.Abort() 而引發 ThreadAbortException 的例外,停止網頁的執行,略過 Response.End 以下的程式碼,並將緩衝輸出的資料傳送到用戶端,然後才直接觸發 HTTP 管線(HTTP Pipelines)的執行鏈結裡的最後一個事件,也就是 HttpApplication.EndRequest 事件。而使用 Response.Redirect 或是 Server.Transfer 也會發生這種例外,因為這兩個方法都會在內部呼叫 Response.End 方法。
解決方案
當了解事實真相後,問題就已不再是"問題"了,而是端看你如何正確的應用。事實上,你無須介入處理 Response.End 所引發的例外狀況,也就是不要把 Response.End 放在 try 區塊中,況且使用 try - catch 陳述式也會比較消耗系統資源,應該斟酌使用。想了解更多例外狀況有關的效能問題,可以參考這裡、這裡。
如果你需要在執行 Response.End、Response.Redirect 或 Server.Transfer 方法之後,仍能繼續執行程式碼,可使用下列作法:
- 使用 HttpContext.Current.ApplicationInstance.CompleteRequest 方法取代 Response.End 。
- 對於 Response.Redirect(url),使用 Response.Redirect(url, false),要求不要結束目前網頁的執行,也就是呼叫 Response.End 方法。
- 使用 Server.Execute 方法代替 Server.Transfer。
HttpApplication.CompleteRequest 跟 Response.End 有何不同呢?
對於 HttpApplication.CompleteRequest 的用途,在 MSDN 文件所得到的解釋如下:
造成 ASP.NET 略過 HTTP 管線的執行鏈結裡的所有事件和篩選,並且直接執行 EndRequest 事件。事實上,如果你是在網頁的 Page_Load 事件處理常式中執行 HttpApplication.CompleteRequest 的話,ASP.NET 仍會處理完 PostBack 所引發的事件,然後才略過其他事件而直接執行 Application_EndRequest 事件。但同樣的狀況,若是改用 Response.End,就會直接結束目前網頁執行,而無法處理 PostBack 所引發的事件。想了解更多關於應用程式與網頁的事件觸發順序,可以參考這裡。
參考文章:
PRB: ThreadAbortException Occurs If You Use Response.End, Response.Redirect, or Server.Transfer by Microsoft
Response.Redirect(url) ThreadAbortException Solution by John S. Reid
In fact, Page events still execute and the Page still processes postback events too. The event pipeline that I am talking about short circuiting with the call to HttpApplication.CompleteRequest() is not the Page event chain but the Application event chain.
匿名
2009年5月15日 下午1:11