ThreadAbortException When Response.End()
5 | 29,253 |
以下這段Code,如果getIdFromDb()傳回"1"時,顯示結果為何?
是"ID=1"嗎? 錯!! 後方還會接上"ERROR:Thread was being aborted."
15 protected void Page_Load(object sender, EventArgs e)
16 {
17 try
18 {
19 string id = getIdFromDb();
20 if (id != null)
21 {
22 Response.Write("ID=" + id);
23 Response.End();
24 }
25 }
26 catch (Exception ex)
27 {
28 Response.Write("<br>ERROR:" + ex.Message);
29 Response.End();
30 }
31 //Do something when id not found
32 //....
33 }
我寫了一個元件,其中有個Complete() Method會直接輸出XML,為了防止後方又被呼叫方Response.Write多餘的文字破壞XML結構,我在Method中呼叫了HttpContext.Current.Reponse.End(),結果呼叫端用try...catch包住Complete(),即使正常執行完成,卻老會在Exception中觸發ThreadAbortException。
Goggle了一下,才發現我並不真的了解Response.End。依據微軟KB 312629的說明,Response.End、Server.Transfer、Response.Redirect被呼叫時,本來就會觸發此一ThreadAbortException(我倒是不理解為何正常的執行流程,卻要夾帶一個Exception,某非是某個SD人員的鋸箭之舉),因此若在try ... catch中包含了這三個執行指令,就會因為ThreadAbortException而跑入catch區段。
依KB的說法,要解決方法包含: 1) 用HttpContext.Current.ApplicationInstance.CompleteRequest();取代Response.End(); 2) 如果是Server.Transfer,可用Server.Execute代替 3) 考慮改用Response.Redirect("...", false) (有程式會繼續往下跑的後遺症)
我還想到的另一種方法是try ... catch時去catch ThreadAbortException後Do Nothing,只是這犯了把Exception當正常邏輯的效能禁忌,所以不應在考量之列。
Comments
# by chicken
哈, 這個問題我也碰過... 明明跟 ASP 一樣的 API, 但是行為卻跟 ASP 不一樣... -_- 有時後這個 exception 不會輸出到 browser 上, 只會在 windows event log 留下記錄.. 熊熊看到 log 一時還真摸不清是啥問題
# by kennyshu
真是相見恨晚... 我debug了好久就是不知道為何老是catch到Thread was being aborted.這個錯誤訊息,原來是我的try catch裡面有很多Response.Redirect(),終於解決了我的疑惑!
# by Robin Lin
經過測試HttpContext.Current.ApplicationInstance.CompleteRequest仍會往下執行後面的程式,所以個人覺得可以使用 retrun 來代替 Response.End,應該就不會出現Exception。
# by Robin Lin
更正: HttpContext.Current.ApplicationInstance.CompleteRequest會中止網頁其他後續事件的引發,所應該是使用HttpContext.Current.ApplicationInstance.CompleteRequest後面在加上return來代替Response.End
# by Jo
或是可以試試看: HttpContext.Current.Response.Flush(); // Sends all currently buffered output to the client. HttpContext.Current.Response.SuppressContent = true; // Gets or sets a value indicating whether to send HTTP content to the client. HttpContext.Current.ApplicationInstance.CompleteRequest(); // Causes ASP.NET to bypass all events and filtering in the HTTP pipeline chain of execution and directly execute the EndRequest event. 雖然不是完全理解這三行在幹嘛但只有這個實測有效TAT 來源:https://stackoverflow.com/questions/20988445/how-to-avoid-response-end-thread-was-being-aborted-exception-during-the-exce