看到有N多的“线程正被中止”异常,而且来自同一个页面。
System.Threading.ThreadAbortException: 线程正被中止。
at System.Threading.Thread.AbortInternal()
at System.Threading.Thread.Abort(Object stateInfo) at System.Web.HttpResponse.End()
at System.Web.HttpServerUtility.Transfer(String path, Boolean preserveForm)
at RPM.Page.LogInHR.btnLogin_Click(Object sender, EventArgs e)
in c:/inetpub/wwwroot/rpm_2/page/login/loginhr.aspx.cs:line 363
虽然捕获了,但并没有跳转到错误页面,但这个信息是在错误页面被写入数据库的!
我做了个试验,在异常信息查询页面跳转到异常信息一览页面
引发异常的页面:
try
{
// 异常一览页面
Server.Transfer("../SystemManagement/ErrorReportView.aspx",false);
}
catch (Exception ex)
{
HttpContext.Current.Session["CurrentError"] = ex.ToString();
HttpContext.Current.Session["CurrentErrorUrl"] = HttpContext.Current.Request.Url.ToString();
// 跳转到异常信息显示页面
HttpContext.Current.Server.Transfer("ErrorReport.aspx",false);
}
异常信息显示页面对异常的处理:
string errortip = "<h4>" + Resources["MEMO_346"] + "</h4>" + "<br><br>";
string error =
"在页面:" + "<br>"
+ (string)Session["CurrentErrorUrl"] +"<br>"
+ "发生了如下异常:" + "<br>"
+ (string)Session["CurrentError"];
// 部署时 不要显示异常信息!
lblErrorMessage.Text = errortip + error;
// 写入数据库
LCW.RPM.BLL.ErrorReport errorReport = new LCW.RPM.BLL.ErrorReport();
LCW.RPM.Model.ErrorReportInfo errorInfo = new LCW.RPM.Model.ErrorReportInfo();
errorInfo.Content = error;
errorInfo.UserName = "sa";
errorReport.Insert(errorInfo);
也就是说实际上,确实跳转到了异常处理页面,并执行了代码,但没等到页面显示,就又跳到了异常信息一览页面,但此时并没有将刚才的异常查询出来,需要刷新页面才会出来。看来确实存在终止线程的问题
MSDN是这么说的:
ThreadAbortException 的引发条件:对
End 的调用已经终止当前请求。
Redirect 调用End,该方法在完成时引发 ThreadAbortException 异常。
对 End、Redirect 和Transfer的调用在当前响应提前结束时引发一个 ThreadAbortException。
End(HttpResponse.End )方法的说明:
将当前所有缓冲的输出发送到客户端,停止该页的执行,并引发 Application_EndRequest 事件。
ThreadAbortException:
在调用 Abort方法以销毁线程时,公共语言运行库将引发 ThreadAbortException。ThreadAbortException 是一种可捕获的特殊异常,但在 catch 块的结尾处它将自动被再次引发。引发此异常时,运行库将在取消线程前执行所有 finally 块。由于线程可以在 finally 块中进行未绑定的计算,因此必须调用Join方法以保证线程已死亡。Join 是一个阻塞调用,它要到线程实际停止执行后才返回。
想不太明白
Update:
看了晓风残月 写的一篇文章 Response.Redirect 与 异常(线程正在中止) ,提到一文:
原来 HttpContext.Current.Server.Transfer("ErrorReport.aspx",false);
是把异常挂起了,所以代码照样执行
按照文章试验了一下:
Response.Redirect(url)等同于Response.Redirect(ur,true),有异常
Response.Redirect(url,false),无异常
Server.Execute(url)无异常
Server.Transfer(url)等同于Server.Transfer(url,true)和Server.Transfer("ErrorReportView.aspx",false);都会出现异常
总之,要想避免异常,就用Response.Redirect(url,false)或Server.Execute(url)。
关于这三者的区别,另开新帖说明。
ps:
偶然发现Server.Execute(url)可以实现那种弹出框提示后紧接着跳转页面的需求,而其他两种情况下弹出框提示信息都不会显示。
注:如果使用 try 、catch 处理包含Response.Redirect 语句代码,总是能捕捉到异常:线程正在中止,
其实不仅仅Response.Redirect 会,Response.End 和 Server.Transfer 也是一样的情况,本质的原因的原因是Response.End 方法停止页的执行,并将该执行变换到应用程序的事件管线中的 Application_EndRequest 事件, Response.End 后面的代码行将不执行。通常认为Response.End 方法是线程的非正常结束,因此MS就在内部抛出ThreadAbortException 异常,而Response.Redirect 和 Server.Transfer 这两种方法都在内部调用 Response.End。