The ThreadAbortException from Response.End()
/// <devdoc> /// <para> /// Terminates execution of the current page and begins execution of a new /// request using the supplied URL path. /// If preserveForm is false, the QueryString and Form collections are cleared. /// </para> /// </devdoc> public void Transfer(string path, bool preserveForm) { Page page = _context.Handler as Page; if ((page != null) && page.IsCallback) { throw new ApplicationException(SR.GetString(SR.Transfer_not_allowed_in_callback)); } // execute child request Execute(path, null, preserveForm); // suppress the remainder of the current one _context.Response.End(); }
都问页面跳转,然后大家都知道Server.Transfer与Request.Redirect的区别。
因为是页面跳转,所以理所应当地被用上了Response.End方法,而此举却引发了一些异常(http://support.microsoft.com/kb/312629)。
所以用Server.Execute就可以避免这个错误了。
详细如下:
对于 Response.End,调用 HttpContext.Current.ApplicationInstance.CompleteRequest 方法而不是 Response.End 以跳过 Application_EndRequest 事件的代码执行。
对于 Response.Redirect,请使用重载 Response.Redirect(String url, bool endResponse),该重载对 endResponse 参数传递 false 以取消对 Response.End 的内部调用。例如:
Response.Redirect ("nextpage.aspx", false);
如果使用此替代方法,将执行 Response.Redirect 后面的代码。
对于 Server.Transfer,请改用 Server.Execute 方法。
顺便让我们看看Response.End都做了些什么
/* * Cancelles handler processing of the current request * throws special [non-]exception uncatchable by the user code * to tell application to stop module execution. */ /// <devdoc> /// <para>Sends all currently buffered output to the client then closes the /// socket connection.</para> /// </devdoc> public void End() { if (_context.IsInCancellablePeriod) { InternalSecurityPermissions.ControlThread.Assert(); Thread.CurrentThread.Abort(new HttpApplication.CancelModuleException(false)); } else { // when cannot abort execution, flush and supress further output if (!_flushing) { // ignore Reponse.End while flushing (in OnPreSendHeaders) Flush(); _ended = true; if (_context.ApplicationInstance != null) { _context.ApplicationInstance.CompleteRequest(); } } } }
关于InternalSecurityPermissions.ControlThread.Assert()请参考http://msdn.microsoft.com/zh-cn/library/system.security.codeaccesspermission.assert(VS.80).aspx
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Threading; namespace WebAppThreadAbortException { public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Do1Nothing(); // Do1NothingWithoutException(); // Do2ResponseEnd(); // Do3Redirect(); // Do4Transfer(); } private void Do1Nothing() { Thread.CurrentThread.Abort(); } private void Do1NothingWithoutException() { try { Thread.CurrentThread.Abort(); } catch { Thread.ResetAbort(); } } private void Do2ResponseEnd() { try { Response.End(); } catch (ThreadAbortException ex) { Response.Write(FormatException(ex.ToString())); } } private void Do3Redirect() { try { Response.Redirect("NextPage.aspx"); } catch (ThreadAbortException ex) { Response.Write(FormatException(ex.ToString())); } } private void Do4Transfer() { try { Server.Transfer("NextPage.aspx"); } catch (ThreadAbortException ex) { Response.Write(FormatException(ex.ToString())); } } private string FormatException(string exception) { return string.Format("<div style=\"border:1px solid; padding:10px; background-color:yellow;\">{0}</div>", exception); } } }
疑问:
既然我们说Response.End将引发一个ThreadAbortException,但为何直接调用Response.End的时候并不会出现异常页面呢?但是我们在页面上直接使用Thread.CurrentThread.Abort(); 却会出现异常页面,请问这是为什么呢?
posted on 2009-06-28 03:38 volnet(可以叫我大V) 阅读(883) 评论(0) 编辑 收藏 举报