當您在 ASP.NET 應用程式中在 HTTPHandler 中使用 Server.Transfer 時,System.Threading.ThreadAbortException

本文可協助您解決當您使用 Server.Transfer 中的 HTTPHandler 方法將控件從某個頁面傳送至 ASP.NET Web 應用程式中的另一個頁面時,可能會擲回錯誤的問題。

原始產品版本: ASP.NET
原始 KB 編號: 817266

徵兆

當您使用 Server.Transfer 中的 HTTPHandler 方法,將控件從某個頁面傳輸到 ASP.NET Web 應用程式中的另一個頁面時,您可能會收到下列錯誤訊息:

System.Threading.ThreadAbortException:正在中止線程。 時間
System.Threading.Thread.AbortInternal() at System.Threading.Thread.Abort() at
System.Web.HttpResponse.End() 的 System.Threading.Thread.Abort(Object stateInfo) at
System.Web.HttpServerUtility.Transfer(字符串路徑,布爾值 preserveForm)

原因

當您呼叫 Server.Transfer時,ASP.NET 會在內部呼叫 Server.Execute 方法來傳輸控件,並呼叫 Response.End 方法來結束目前頁面的處理。 Response.End 結束頁面執行並呼叫 Thread.Abort 方法。 方法 Thread.Abort 會導致 ThreadAbortException 錯誤訊息出現。

因應措施

若要解決此問題,請使用 Server.Execute ,而不是 Server.Transfer 在 的 方法HTTPHandler中使用 ProcessRequest 。 修改 ProcessRequest 過的方法如下所示:

  • C# 範例程式碼 (英文)

    public void ProcessRequest(HttpContext context)
    {
        try
        {
           context.Server.Execute("WebForm1.aspx");
        }
        catch(System.Exception e)
        {
           context.Response.Write(e.StackTrace);
           context.Response.Write(e.ToString());
        }
    }
    
  • Visual Basic 範例程序代碼

    Public Sub ProcessRequest(ByVal context As HttpContext) _
           Implements IHttpHandler.ProcessRequest
        Try
           context.Server.Execute("WebForm1.aspx")
        Catch e As Exception
           context.Response.Write(e.StackTrace)
        End Try
    End Sub
    

狀態

這是依照設計的行為。

重現行為的步驟

  1. 在 Microsoft Visual Studio 中,使用 Visual Basic 或 C# 建立新的 ASP.NET Web Form Application 專案。 根據預設, 會建立WebForm1.aspx 。 將專案 命名為 ServerTransferTest

  2. 以滑鼠右鍵按兩下 WebForm1.aspx ,然後選取 [ 檢視 HTML 來源]。

  3. 以下列範例程式代碼取代現有的程式代碼:

    <%@ Page %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
    <HTML>
       <HEAD>
          <title>WebForm1</title>
       </HEAD>
       <body MS_POSITIONING="GridLayout">
          <form id="Form1" method="post" runat="server">
             <asp:HyperLink id="HyperLink1" style="Z-INDEX: 101; LEFT: 324px; POSITION: absolute; TOP: 181px" runat="server" NavigateUrl="http://localhost/ServerTransferTest/test.ashx"> http://localhost/ServerTransferTest/test.ashx</asp:HyperLink>
             <asp:Label id="Label1" style="Z-INDEX: 102; LEFT: 292px; POSITION: absolute; TOP: 149px" runat="server">On Clicking this URL should not throw any exception</asp:Label>
          </form>
       </body>
    </HTML>
    
  4. 按兩下 WebForm1.aspx 的設計檢視,然後使用下列範例程式代碼取代程式代碼後置頁面中的結束程式代碼:

    • C# 範例程式碼 (英文)

      using System;
      using System.Web;
      using System.Web.UI.WebControls;
      
      namespace ServerTransferTest
      {
         /// <summary>
         /// Summary description for WebForm1.
         /// </summary>
         public class WebForm1 : System.Web.UI.Page
         {
            protected System.Web.UI.WebControls.Label Label1;
            protected System.Web.UI.WebControls.HyperLink HyperLink1;
      
            private void Page_Load(object sender, System.EventArgs e)
            {
            }
      
            #region Web Form Designer generated code
            override protected void OnInit(EventArgs e)
            {
               // CODEGEN: ASP.NET Web Form Designer requires this call.
               InitializeComponent();
               base.OnInit(e);
            }
      
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method by using the code editor.
            /// </summary>
            private void InitializeComponent()
            {
               this.Load += new System.EventHandler(this.Page_Load);    
            }
            #endregion
         }
      }
      
    • Visual Basic 範例程序代碼

      Public Class WebForm1
          Inherits System.Web.UI.Page
          Protected WithEvents Label1 As System.Web.UI.WebControls.Label
          Protected WithEvents HyperLink1 As System.Web.UI.WebControls.HyperLink
      
          'Web Form Designer requires this call.
          <System.Diagnostics.DebuggerStepThrough()>
          Private Sub InitializeComponent()
          End Sub
      
          Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
             'CODEGEN: Web Form Designer requires this method call.
             'Do not modify it by using the code editor.
             InitializeComponent()
          End Sub
      
          Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
             'Put user code to initialize the page here
          End Sub
      End Class
      
  5. 在 [ 檔案] 功能表上,選取 [ 新增專案]。

  6. 在 [新增專案] 下,選取 [類別]。 在 [新增專案] 下的 [名稱] 文本框中,重新命名 類別HelloWorldHandler,然後選取 [開啟]。

  7. 以下列範例程式代碼取代類別檔案中的 HelloWorldHandler 現有程式代碼:

    • C# 範例程式碼 (英文)

      using System.Web;
      namespace ServerTransferTest
      {
          public class HelloWorldHandler : IHttpHandler
          {
             public void ProcessRequest(HttpContext context)
             {
                try
                {
                   context.Server.Transfer("WebForm1.aspx", true );
                }
                catch(System.Exception e)
                {
                   context.Response.Write(e.StackTrace);
                   context.Response.Write(e.ToString());
                }
             }
             public bool IsReusable
             {
                // To enable pooling, return true here.
                // This keeps the handler in memory.
                get { return false; }
             }
          }
      }
      
    • Visual Basic 範例程序代碼

      Imports System
      Imports System.Web
      
      Public Class HelloWorldHandler
          Implements IHttpHandler
          Public Sub ProcessRequest(ByVal context As HttpContext) _
             Implements IHttpHandler.ProcessRequest
             Try
                ' context.Server.Transfer("WebForm1.aspx", True)
                context.Server.Execute("WebForm1.aspx")
             Catch e As Exception
                context.Response.Write(e.StackTrace)
             End Try
          End Sub
          ' Override the IsReusable property.
          Public ReadOnly Property IsReusable() As Boolean _
             Implements IHttpHandler.IsReusable
             Get
                Return True
             End Get
          End Property
      End Class
      
  8. 重複步驟 5 和 6 以新增另一個類別檔案。 重新命名類別檔案 HelloWorldHandlerFactory

  9. 以下列範例程式代碼取代類別檔案中的 HelloWorldHandlerFactory 現有程式代碼:

    • C# 範例程式碼 (英文)

      using System.Web;
      namespace ServerTransferTest
      {
          public class HelloWorldHandlerFactory : IHttpHandlerFactory
          {
             public IHttpHandler GetHandler( HttpContext context, System.String requestType, System.String url, System.String pathTranslated)
             {
                HttpResponse Response = context.Response;
                Response.Write("<html>");
                Response.Write("<body>");
                Response.Write("<h1> Hello from HelloWorldHandlerFactory.GetHandler </h1>");
                Response.Write("</body>");
                Response.Write("</html>");
                return new HelloWorldHandler();
             }
             public void ReleaseHandler( IHttpHandler handler )
             {
             }
          }
      }
      
    • Visual Basic 範例程序代碼

      Imports System
      Imports System.Web
      Public Class HelloWorldHandlerFactory
          Implements IHttpHandlerFactory
          Public Overridable Function GetHandler(ByVal context As HttpContext, _
          ByVal requestType As String, ByVal url As String, ByVal pathTranslated As String) _
             As IHttpHandler _
             Implements IHttpHandlerFactory.GetHandler
      
             Dim Response As HttpResponse = context.Response
             Response.Write("<html>")
             Response.Write("<body>")
             Response.Write("<h1> Hello from HelloWorldHandlerFactory.GetHandler </h1>")
             Response.Write("</body>")
             Response.Write("</html>")
             Return New HelloWorldHandler()
          End Function
      
          Public Overridable Sub ReleaseHandler(ByVal handler As IHttpHandler) _
             Implements IHttpHandlerFactory.ReleaseHandler
          End Sub
      End Class
      
  10. 開啟 web.config 檔案,然後在 區段中新增 <httpHandlers> 區段<system.web>,如下所示:

    <configuration>
        <system.web>
            <httpHandlers>
                <add verb="*" path="*.ashx" type="ServerTransferTest.HelloWorldHandlerFactory,ServerTransferTest" />
            </httpHandlers>
        .....
        </system.web>
    </configuration>
    
  11. 在 [偵錯] 功能表上,選取 [開始],然後在WebForm1.aspx選取下列超連結:

    http://localhost/ServerTransferTest/test.ashx

參考資料