当调用ASP.NET System.Web.HttpResponse.End()时,当前线程会被中止?

19

当调用System.Web.HttpResponse.End()时,会触发System.Thread.Abort,我猜测这是一个异常?我有一些日志文件,在日志文件中列出了这个信息...

A first chance

exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll
12/14/2008 01:09:31::
Error in Path :/authenticate
Raw Url :/authenticate
Message :Thread was being aborted.
Source :mscorlib
Stack Trace :   at System.Threading.Thread.AbortInternal()
   at System.Threading.Thread.Abort(Object stateInfo)
   at System.Web.HttpResponse.End()
   at DotNetOpenId.Response.Send()
   at DotNetOpenId.RelyingParty.AuthenticationRequest.RedirectToProvider()
   at MyProject.Services.Authentication.OpenIdAuthenticationService.GetOpenIdPersonaDetails(Uri serviceUri) in C:\Users\Pure Krome\Documents\Visual Studio 2008\Projects\MyProject\Projects\Services\Authentication\OpenIdAuthenticationService.cs:line 108
   at MyProject.Mvc.Controllers.AuthenticationController.Authenticate() in C:\Users\Pure Krome\Documents\Visual Studio 2008\Projects\MyProject\Projects\MVC Application\Controllers\AuthenticationController.cs:line 69
TargetSite :Void AbortInternal()
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in Ackbar.Mvc.DLL
An exception of type 'System.Threading.ThreadAbortException' occurred in Ackbar.Mvc.DLL but was not handled in user code

这种行为是否正常?有没有优雅地中止而不是(看起来像)突然中止的方式?

更新

到目前为止,普遍认为这是设计上的问题。因此,我想知道我们是否能够采取这个问题,并查看是否可以调整代码,使其不像我们提前终止线程一样并且优雅地退出...是否可能?有代码示例吗?


2
嗨, 除了下面的答案,您可能还想检查以下内容: http://support.microsoft.com/kb/312629/EN-US/ - Milen
请参见相关的 response-end-considered-harmful - Michael Freidgeim
5个回答

11

没有所谓“优雅”的中止。不过,您可以选择仅刷新响应而非结束响应,让框架为您关闭连接。在此情况下,我假设您希望将响应发送给客户端,即典型情况。

根据MSDN的说法,在响应过早结束时调用Response.End()会抛出ThreadAbortException异常。只有在需要引发异常时才应调用Response.End()。


1
我一直想知道在这种情况下“过早”这个词的确切定义是什么...有没有记录在案?我一直认为它的意思是“如果在调用Response.End()之后还有代码需要执行”。 - Dave Markle

6

是的,这确实是设计上的。微软甚至已经将其记录下来。否则你怎么能停止程序的其他部分执行呢?


请查看 response-end-considered-harmful 问题的答案。 - Michael Freidgeim

3

当异常递归到堆栈顶部以停止当前执行时,这并没有什么本质的不优雅之处。毕竟,你抛出异常并在某个较低的位置捕获它也是如此。

我建议从日志中过滤掉它。如果你使用ASP.Net健康监控,你可以将每个异常配置/映射到给定提供程序(事件日志、邮件等)来控制是否对线程异常收到通知。如果是自定义日志记录,则只需添加一个if来检查它。

请注意,你无法捕获ThreadAbortException异常,因此即使你的日志记录代码执行类似于catch(Exception e) { // log exception and then do not throw again }的操作,一旦你的catch块退出,框架仍然会再次引发ThreadAbortException异常。


2
我一直尽量避免使用异常,除非遇到了意料之外的情况。从我的角度来看,如果我们想要重定向,那是可以预料的,因此我们知道我们要做什么(停止当前操作,转到新的URI)。。所以我不明白他们为什么没有优雅地结束它。 - Pure.Krome
所以我认为我倾向于同意你的观点,即不应该以这种方式设计库。尽管如此,我实在想不出任何在 .Net 框架中可能实现它的方法而不使用异常。在这种情况下,无论是否预期,都需要抛出异常。 - Peter Oehlert

0

我尝试了以上所有更改,但我的Web应用程序仍然出现相同的问题。

然后我联系了我的托管提供商,并要求他们检查是否有任何软件或防病毒软件通过HTTP阻止我们的文件传输,或者ISP/网络不允许文件传输。

他们检查了服务器设置,并为我的服务器绕过了“数据中心共享防火墙”,现在我们的应用程序开始下载文件。

希望这个答案能帮到别人。这就是对我有效的解决方法。


0
不要使用Response.End()方法,因为它使用Application.End()并停止应用程序。进一步使用HTTP请求或响应违反页面生命周期。请使用HttpContext.Current.Response.Close()或HttpContext.Current.ApplicationInstance.CompleteRequest();

请翻译下面与程序相关的内容,从英文到中文。只返回翻译文本:请添加来源,以便更清楚地引用。 Source: Unknown - lalithkumar
HttpContext.Current.Response.Clear(); HttpContext.Current.Response.ClearHeaders(); HttpContext.Current.Response.Buffer = true; HttpContext.Current.Response.ContentType = "application/ms-excel"; HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + FileToDownLoad.Name); HttpContext.Current.Response.Charset = "utf-8"; HttpContext.Current.Response.WriteFile(FileToDownLoad.FullName); HttpContext.Current.Response.Flush(); HttpContext.Current.Response.Close(); HttpContext.Current.ApplicationInstance.CompleteRequest(); - shhhhh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接