在我的应用程序中,我从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'
发生了'System.Threading.ThreadAbortException'类型的异常 mscorlib.dll但未在用户代码中处理
在我的VS2010的输出窗口中。
为什么我会收到此异常,如何解决此问题?
答案 0 :(得分:9)
Response.Redirect(someUrl, false)
,然后致电CompleteRequest()
将false传递给Response.Redirect(...)
会阻止ThreadAbortException
被提升,但是通过调用CompleteRequest()
来结束页面生命周期仍然很重要。
在页面处理程序中使用此方法终止请求时 一页并开始另一页的新请求,将endResponse设置为 false和然后调用CompleteRequest()方法。如果指定true 对于endResponse参数,此方法调用End方法 原始请求,抛出ThreadAbortException异常 当它完成。此异常对Web有不利影响 应用程序性能,这就是为什么传递false的原因 建议使用endResponse参数。有关更多信息,请参阅 结束方法。
请注意,调用Response.Redirect(...)
方法时,会生成一个具有全新页面生命周期的新线程,以处理新的重定向响应。新响应完成后,会在原始响应上调用Response.End()
,最终会引发ThreadAbortException
并引发EndRequest
事件。如果您阻止调用Response.End()
(通过将false传递给Response.Redirect
),则需要致电CompleteRequest()
,其中包含:{/ p>
使ASP.NET绕过HTTP管道中的所有事件和过滤 执行链并直接执行EndRequest事件。
如果您致电Response.Redirect(someUrl, false)
允许代码继续执行,您可能需要更改代码,以便正常停止处理。有时,这就像向void方法调用添加return
一样简单。但是,如果你处于一个深层调用堆栈中,这会更加棘手,如果你不想要更多的代码执行它可能更容易传递真如Response.Redirect(someUrl, true)
并故意期望ThreadAbortException
- 由这种方式并不是一件坏事,你应该在Response.Redirect(...)
和Server.Transfer(...)
来电时期待它。
ThreadAbortException不是普通的异常。即使将代码包装在try catch块中,也会在finally子句之后立即引发ThreadAbortException。
当调用Abort方法来销毁一个线程时, 公共语言运行库抛出ThreadAbortException。 ThreadAbortException是一个可以捕获的特殊异常,但它 将在catch块结束时再次自动引发。什么时候 引发此异常,运行时执行所有finally块 在结束线程之前。因为线程可以做无界限 在finally块中计算或调用Thread.ResetAbort来取消 中止,无法保证线程永远不会结束。如果你 想要等到中止的线程结束,你可以调用 Thread.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);
}
}
答案 1 :(得分:0)
这是由Response.Redirect
引起的标准异常,只有当您对执行重定向的块有明确try-catch
时才会捕获。 ASP.NET在重定向时抛出它,以便在重定向后不执行代码。
解决方案是添加一个空捕获以吞下此特定异常
try {
...
Response.Redirect( ... );
}
catch ( ThreadAbortException ) { } // swallow the exception
catch ( Exception ex ) {
// an existing catch clause
}
答案 2 :(得分:0)
不要只是抓住异常。使用带有布尔值的Redirect重载。传递false表示您不希望线程中止。