以下這段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

Post a comment


31 + 12 =