c# - Response.Redirect 引起的 System.Threading.ThreadAbortException

标签 c# asp.net exception response webmethod

在我的应用程序中,我从 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>

我得到:

A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll

An exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll but was not handled in user code

在我的 VS2010 的输出窗口中。

为什么我会收到此异常,我该如何解决?

最佳答案

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

将 false 传递给 Response.Redirect(...) 将防止引发 ThreadAbortException,但是通过调用 CompleteRequest() 结束页面生命周期仍然很重要。

When you use this method in a page handler to terminate a request for one page and start a new request for another page, set endResponse to false and then call the CompleteRequest() method. If you specify true for the endResponse parameter, this method calls the End method for the original request, which throws a ThreadAbortException exception when it completes. This exception has a detrimental effect on Web application performance, which is why passing false for the endResponse parameter is recommended. For more information, see the End method.

请注意,当调用 Response.Redirect(...) 方法时,会生成一个具有全新页面生命周期的新线程来处理新的重定向响应。当新响应完成时,它会在原始响应上调用 Response.End(),最终抛出 ThreadAbortException 并引发 EndRequest 事件。如果您阻止 Response.End() 被调用(通过将 false 传递给 Response.Redirect),那么您需要调用 CompleteRequest(),其中:

Causes ASP.NET to bypass all events and filtering in the HTTP pipeline chain of execution and directly execute the EndRequest event.

注意事项:

如果您调用 Response.Redirect(someUrl, false) 允许代码继续执行,您可能需要更改代码以便正常停止处理。有时这就像将 return 添加到 void 方法调用一样简单。但是,如果您处于深度调用堆栈中,这会更加棘手,如果您不希望执行更多代码,则传递 true 可能更容易,例如 Response.Redirect(someUrl, true) 并且有意期待 ThreadAbortException - 顺便说一下,这不是一件坏事,你应该在 Response.Redirect(...)Server.Transfer( ...) 调用。

ThreadAbortException 无法通过捕获异常来停止

ThreadAbortException 不是您的普通异常。即使您将代码包装在 try catch block 中,ThreadAbortException 也会在 finally 子句之后立即引发。

When a call is made to the Abort method to destroy a thread, the common language runtime throws a ThreadAbortException. ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block. When this exception is raised, the runtime executes all the finally blocks before ending the thread. Because the thread can do an unbounded computation in the finally blocks or call Thread.ResetAbort to cancel the abort, there is no guarantee that the thread will ever end. If you want to wait until the aborted thread has ended, you can call the Thread.Join method. Join is a blocking call that does not return until the thread actually stops executing.

通常我在代码中看到的是围绕 Response.Redirect 的 try catch block ,它将记录不是 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);
   }
}

关于c# - Response.Redirect 引起的 System.Threading.ThreadAbortException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9964620/

相关文章:

c# - 发送文件上传到WCF

c# - 如何在运行时在 GridView 中添加动态文本框?

java - 致命异常 : Timer-0?

c# - 是否有理由以这种方式进行类型比较?

c# - 找不到类型或命名空间名称...

c# - WPF 控件的条件加载

javascript - 如何让 Chrome 在更改 url 失败时抛出异常

c# - 如何使用 C# 混合颜色 "naturally"?

c# - 从 asp.net 中的代码后面调用 jquery 函数似乎不起作用

java - 获取 XML 包中返回的 SQLException 消息?