【问题标题】:When an ASP.NET System.Web.HttpResponse.End() is called, the current thread is aborted?当调用 ASP.NET System.Web.HttpResponse.End() 时,当前线程被中止?
【发布时间】:2010-09-26 18:52:58
【问题描述】:

当 System.Web.HttpResponse.End() 被调用时 System.Thread.Abort 被触发,我猜这是(或触发)异常?我有一些日志记录,这已在日志文件中列出...

第一次机会

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

这是正常行为吗?是否可以优雅地中止而不是(看起来像)突然中止?

更新

到目前为止,普遍的人口普​​查是by design。所以我想知道我们是否有可能接受这个问题,看看我们是否可以调整代码以使其感觉不像我们正在结束线程过早并优雅地退出......可能吗?代码示例?

【问题讨论】:

标签: asp.net httpresponse thread-abort


【解决方案1】:

没有所谓的“优雅”中止。不过,您可以简单地 Flush() 响应,而不是结束它并让框架为您关闭连接。在这种情况下,我假设您希望将响应发送给客户端,即典型情况。

根据MSDN,当响应提前结束时,调用 Response.End() 会抛出 ThreadAbortException。你真的应该只在想要引发异常时调用 Response.End()。

【讨论】:

  • 我一直想知道在这种情况下“过早”的确切定义是什么......这在任何地方都有记录吗?我一直认为它的意思是“如果在调用 Response.End() 后有代码要执行”。
【解决方案2】:

是的,这确实是设计使然。微软甚至有documented它。否则您将如何阻止程序的其余部分执行?

【讨论】:

【解决方案3】:

异常递归到堆栈以停止当前执行本身并没有什么不优雅的。当然只是你抛出一个异常并在异常中的某个较低位置捕获它。

我会考虑从您的日志中过滤它。如果您使用 ASP.Net 健康监控,您可以配置/映射每个异常到给定的提供程序(事件日志、邮件等),以控制是否收到有关线程中止异常的通知。如果它是自定义日志记录,那么我只需添加一个 if 来检查它。

请注意,您不能吃 ThreadAbortException,因此即使您的日志记录代码正在执行类似catch(Exception e) { // log exception and then do not throw again } 的操作,一旦您的 catch 块退出,框架仍会再次引发 ThreadAbortException。

【讨论】:

  • 我总是尽量避免异常,除非有什么意外。从我的角度来看,如果我们想重定向,那是预期的 ..所以这样,我们知道我们正在尝试做什么(停止当前的东西,转到新的 URI)..所以我不看看他们为什么没有优雅地结束。
  • 所以我想我倾向于同意你的观点,你不应该以这种方式设计库。尽管如此,我真的想不出任何方法可以毫无例外地在.Net框架中实现。在这种情况下,无论预期与否,都会调用异常。
【解决方案4】:

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

【讨论】:

  • 请添加来源。如果有人参考,这将有助于更清楚
  • HttpContext.Current.Response.Clear(); HttpContext.Current.Response.ClearHeaders(); HttpContext.Current.Response.Buffer = true; HttpContext.Current.Response.ContentType = "应用程序/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();
【解决方案5】:

我使用了上述所有更改,但我的 Web 应用程序仍然遇到同样的问题。

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

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

希望这个答案对某人有所帮助。这对我有用

【讨论】:

    猜你喜欢
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多