簡體   English   中英

由Response.Redirect引起的System.Threading.ThreadAbortException

[英]System.Threading.ThreadAbortException caused by Response.Redirect

在我的應用程序中,我從JavaScript調用WebMethod,我試圖重定向到某個頁面:

[WebMethod]
public string Logout() {            
    if (User.Identity.IsAuthenticated) {                            
        HttpContext.Current.Response.Redirect("~/Pages/Logout.aspx");               
    }
    return "";
}

aspx頁面:

    <input onclick="callLogout();" id="btn" type="button" value="Click Me" />

    <asp:ScriptManager ID="ScriptManager" runat="server">
        <Services>
            <asp:ServiceReference Path="~/WebServices/EMSWebService.asmx" />
        </Services>
    </asp:ScriptManager>
    <script type="text/javascript">        
        function callLogout() {
            EMSApplication.Web.WebServices.EMSWebService.Logout(OnComplete, OnError);
        }

        function OnComplete(result) {
            alert(result);
        }

        function OnError(result) {
            alert(result.get_message());
        }
    </script>

我得到了:

mscorlib.dll中出現'System.Threading.ThreadAbortException'類型的第一次機會異常

mscorlib.dll中出現“System.Threading.ThreadAbortException”類型的異常,但未在用戶代碼中處理

在我的VS2010的輸出窗口中。

為什么我會收到此異常,如何解決此問題?

重定向的理想方法是調用Response.Redirect(someUrl, false)然后調用CompleteRequest()

將false傳遞給Response.Redirect(...)將阻止引發ThreadAbortException ,但是通過調用CompleteRequest()來結束頁面生命周期仍然很重要。

在頁面處理程序中使用此方法終止對一個頁面的請求並為另一個頁面啟動新請求時,請將endResponse設置為false, 然后調用CompleteRequest()方法 如果為endResponse參數指定true,則此方法為原始請求調用End方法,該方法在完成時拋出ThreadAbortException異常。 此異常對Web應用程序性能有不利影響,這就是建議為endResponse參數傳遞false的原因。 有關更多信息,請參閱End方法。

請注意,當調用Response.Redirect(...)方法時,會生成一個帶有全新頁面生命周期的新線程來處理新的重定向響應。 當新響應完成時,它會對原始響應調用Response.End() ,最終會拋出ThreadAbortException並引發EndRequest事件。 如果阻止調用Response.End() (通過將false傳遞給Response.Redirect ),則需要調用CompleteRequest() ,其中:

導致ASP.NET繞過HTTP管道執行鏈中的所有事件和過濾,並直接執行EndRequest事件。

謹慎之言:

如果您調用Response.Redirect(someUrl, false)允許代碼繼續執行,您可能希望更改代碼,以便處理正常停止。 有時這就像添加return void方法調用一樣簡單。 但是,如果你處於一個深度調用堆棧中,這會更加棘手,如果你不想要更多的代碼執行它可能更容易傳遞真如Response.Redirect(someUrl, true)並故意期望ThreadAbortException - 由方式並不是一件壞事,你應該期待它在Response.Redirect(...)Server.Transfer(...)調用期間。

捕獲異常無法停止ThreadAbortException

ThreadAbortException不是普通的異常。 即使將代碼包裝在try catch塊中,ThreadAbortException也會在finally子句之后立即引發。

當調用Abort方法來銷毀線程時,公共語言運行庫會拋出ThreadAbortException。 ThreadAbortException是一個可以捕獲的特殊異常,但它會在catch塊的末尾自動再次引發 引發此異常時,運行時會在結束線程之前執行所有finally塊。 因為線程可以在finally塊中執行無限制計算或調用Thread.ResetAbort來取消中止 ,所以無法保證線程將永遠結束。 如果要等到中止的線程結束,可以調用Thread.Join方法。 Join是一個阻塞調用,在線程實際停止執行之前不會返回。

通常我在代碼中看到的是一個圍繞Response.Redirect的try catch塊,它將記錄不是ThreadAbortExceptions的異常(因為你期望那些)。 例:

private void SomeMethod()
{
   try
   {
      // Do some logic stuff
      ...

      if (someCondition)
      {
         Response.Redirect("ThatOneUrl.aspx", true);
      }
   }
   catch (ThreadAbortException)
   {
      // Do nothing.  
      // No need to log exception when we expect ThreadAbortException
   }
   catch (Exception ex)
   {
      // Looks like something blew up, so we want to record it.
      someLogger.Log(ex);
   }
}

這是一個標准的異常,只有當你對執行重定向的塊有一個顯式的try-catch才會捕獲到Response.Redirect ASP.NET在重定向時拋出它,以便在重定向后不執行任何代碼。

一個解決方案是添加一個空的catch來吞下這個特殊的異常

try {
   ...
   Response.Redirect( ... );
}
catch ( ThreadAbortException ) { } // swallow the exception
catch ( Exception ex ) { 
   // an existing catch clause
}

不要只是抓住異常。 使用帶有布爾值的Redirect重載。 傳遞false表示您不希望線程中止。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM