This KB Article说ASP.NET的Response.End()
中止了一个帖子。
Reflector显示它看起来像这样:
public void End()
{
if (this._context.IsInCancellablePeriod)
{
InternalSecurityPermissions.ControlThread.Assert();
Thread.CurrentThread.Abort(new HttpApplication.CancelModuleException(false));
}
else if (!this._flushing)
{
this.Flush();
this._ended = true;
if (this._context.ApplicationInstance != null)
{
this._context.ApplicationInstance.CompleteRequest();
}
}
}
这对我来说似乎很苛刻。正如知识库文章所说,Response.End()
之后的应用程序中的任何代码都不会被执行,这违反了最不惊讶的原则。它几乎像WinForms应用程序中的Application.Exit()
。 Response.End()
导致的线程中止异常无法捕获,因此围绕try
... finally
中的代码将无法满足。
这让我想知道我是否应该总是避免Response.End()
。
在Response.End()
和Response.Close()
时,有人可以建议何时使用HttpContext.Current.ApplicationInstance.CompleteRequest()
?
根据我收到的输入,我的答案是,是的,Response.End
是有害的,但在某些有限的情况下它很有用。
Response.End()
作为无法捕获的投掷,以便在异常情况下立即终止HttpResponse
。在调试过程中也很有用。 避免Response.End()
完成例行回复。 Response.Close()
立即关闭与客户端的连接。根据{{3}},此方法不适用于正常的HTTP请求处理。您不太可能有充分理由调用此方法。CompleteRequest()
结束正常请求。当前CompleteRequest
事件完成后,EndRequest
会导致ASP.NET管道跳转到HttpApplication
事件。因此,如果您调用CompleteRequest
,然后将更多内容写入响应,则写入将发送到客户端。 编辑 - 2011年4月13日
此处可提供更清晰的信息:
- this MSDN blog post
- Useful post on MSDN Blog
答案 0 :(得分:105)
最初我曾建议您只需将所有来电替换为 [Response.End]与[...] CompleteRequest()调用,但如果你想避免 回发处理和html渲染,你需要添加[...]覆盖 好。
Jon Reid,“最终分析”
Server.Transfer,Response.Redirect,Response.End方法全部引发 例外。这些方法中的每一个都在内部调用Response.End。打电话给 Response.End,反过来,causes a ThreadAbortException exception。
HttpApplication.CompleteRequest()设置一个导致线程的变量 跳过HttpApplication事件管道中的大多数事件[ - ]而不是 页面事件链,但是应用程序事件链。
...
创建一个类级别变量,标记页面是否应该终止然后 在处理事件或呈现页面之前检查变量。 [...] 我建议只overriding the RaisePostBackEvent and Render methods
当正常的请求处理时,Response.End和Response.Close不被使用 表现很重要。 Response.End是一种方便,严厉的手段 终止请求处理以及相关的性能损失。 Response.Close用于在IIS /套接字上立即终止HTTP响应 等级并导致KeepAlive之类的问题。
结束ASP.NET请求的推荐方法是 HttpApplication.CompleteRequest。请记住,ASP.NET渲染将具有 由于HttpApplication.CompleteRequest跳过剩下的部分,因此要手动跳过 IIS / ASP.NET应用程序管道,而不是ASP.NET页面管道(即 应用程序管道中的一个阶段。)
Copyright © 2001-2007, C6 Software, Inc我能说得最清楚。
使ASP.NET绕过HTTP管道链中的所有事件和过滤 执行并直接执行EndRequest事件。
此方法仅提供与ASP的兼容性 - 即for 与先前基于COM的Web编程技术的兼容性 ASP.NET.preceded ASP.NET。 [强调补充]
此方法以突然方式终止与客户端的连接 不适用于正常的HTTP请求处理。 [强调补充]
答案 1 :(得分:94)
此问题出现在所有谷歌搜索的顶部附近有关response.end的信息,因此对于像我这样的其他搜索,如果希望发布CSV / XML / PDF等以响应事件而不渲染整个ASPX页面,这就是如何我做到了(对于这样一个简单的任务IMO,覆盖渲染方法过于复杂)
// Add headers for a csv file or whatever
Response.ContentType = "text/csv"
Response.AddHeader("Content-Disposition", "attachment;filename=report.csv")
Response.AddHeader("Pragma", "no-cache")
Response.AddHeader("Cache-Control", "no-cache")
// Write the data as binary from a unicode string
Dim buffer As Byte()
buffer = System.Text.Encoding.Unicode.GetBytes(csv)
Response.BinaryWrite(buffer)
// Sends the response buffer
Response.Flush()
// Prevents any other content from being sent to the browser
Response.SuppressContent = True
// Directs the thread to finish, bypassing additional processing
HttpContext.Current.ApplicationInstance.CompleteRequest()
答案 2 :(得分:63)
如果您在自己的应用中使用了异常记录器,则会使用这些良性ThreadAbortException
来电中的Response.End()
对其进行淡化。我认为这是微软的说法“敲掉它!”。
如果有一些异常情况并且没有其他可能的行动,我只会使用Response.End()
。也许那时,记录此异常实际上可能表示警告。
答案 3 :(得分:11)
关于“我仍然不知道Response.Close和CompleteRequest()之间的区别”我会说:
更喜欢CompleteRequest(),不要使用Response.Close()。
有关此案例的完善摘要,请参阅following article。
请注意,即使在调用CompleteRequest()之后,某些文本(例如,从ASPX代码重新编译)也会附加到响应输出流中。您可以通过覆盖following article中所述的Render和RaisePostBackEvent方法来阻止它。
BTW:我同意阻止使用Response.End(),特别是在将数据写入http流以模拟文件下载时。我们过去曾使用过Response.End(),直到我们的日志文件充满了ThreadAbortExceptions。
答案 4 :(得分:9)
我不同意声明“ Response.End is harm ”。这绝对没有害处。 Response.End做它说的话;它结束了页面的执行。使用反射器来查看它的实现方式只应被视为具有指导性。
我的2cent建议书
避免使用Response.End()
作为控制流
DO 如果您需要停止请求执行,请使用Response.End()
并注意(通常)*没有代码会在该点之后执行。
* Response.End()
和ThreadAbortException s。
Response.End()
抛出一个ThreadAbortException作为其当前实现的一部分(如OP所述)。
ThreadAbortException是一个可以捕获的特殊异常,但是 它将在catch块结束时自动再次提升。
要了解如何编写必须处理ThreadAbortExceptions的代码,请参阅@ Mehrdad对SO How can I detect a threadabortexception in a finally block的回复,其中他引用了RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup Method和Constrained Execution Regions
提到的Rick Strahl article具有指导意义,请务必阅读评论。请注意,Strahl的问题是具体的。他希望将数据传输到客户端(图像),然后处理命中跟踪数据库更新,这不会减慢图像的服务速度,这使他在调用Response.End后做了一些事情。< / p>
答案 5 :(得分:4)
我从未考虑过使用Response.End()来控制程序流程。
然而,在向用户提供文件时,Response.End()可能很有用。
您已将该文件写入回复,并且您不希望将任何其他内容添加到回复中,因为它可能会损坏您的文件。
答案 6 :(得分:2)
我在.NET和Classic ASP中都使用了Response.End()来强制结束之前的事情。例如,我在有一定数量的登录尝试时使用它。或者,当从未经身份验证的登录中接收安全页面时(粗略示例):
if (userName == "")
{
Response.Redirect("......");
Response.End();
}
else
{
.....
向用户提供文件时,我会使用Flush,End会导致问题。
答案 7 :(得分:2)
我只使用Response.End()作为测试/调试机制
<snip>
Response.Write("myVariable: " + myVariable.ToString());
Response.End();
<snip>
根据您在研究方面发布的内容,我认为如果需要Response.End
那将是一个糟糕的设计。答案 8 :(得分:0)
在经典的asp上,在一些ajax调用中,我的TTFB(第一个字节的时间)为3到10秒,比在具有更多SQL调用的常规页面上的TTFB大得多。
返回的ajax是一段要注入到页面中的HTML。
TTFB比渲染时间长几秒钟。
如果我在渲染后添加了response.end,则TTFB大大减少了。
我可以通过发出“