ThreadAbortException When Response.End()
以下這段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當正常邏輯的效能禁忌,所以不應在考量之列。