如何避免Response.End()“线程被中止”Excel文件下载期间出现异常

问题描述 投票:83回答:14

我试图将我的数据集转换为excel并下载excel。我得到了我所需的excel文件。但每次excel下载都会引发System.Threading.ThreadAbortException。如何解决这个问题?请帮帮我...

我在我的aspx屏幕中调用此方法。此方法也引发了同样的异常。

我在许多aspx屏幕中调用public void ExportDataSet(DataSet ds)函数,并且我正在为运行时引发的异常维护错误记录器方法,将这些异常写入.txt文件。所以在所有aspx屏幕的txt文件中记录了相同的异常。我只想避免从方法声明的类文件抛出到aspx的异常抛出。我只是想在我的方法声明类文件本身处理这个异常。

ASPX文件方法调用:excel.ExportDataSet(dsExcel);

方法定义:

public void ExportDataSet(DataSet ds)
{

   try
   {
      string filename = "ExcelFile.xls";
      HttpResponse response = HttpContext.Current.Response;
      response.Clear();
      response.Charset = "";
      response.ContentType = "application/vnd.ms-excel";
      response.AddHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
      using (StringWriter sw = new StringWriter())
      {
         using (HtmlTextWriter htw = new HtmlTextWriter(sw))
         {
             GridView dg = new GridView();
             dg.DataSource = ds.Tables[0];
             dg.DataBind();
             dg.RenderControl(htw);
             // response.Write(style);
             response.Write(sw.ToString());                                                
             response.End();                    // Exception was Raised at here
         }
      }
   }
   catch (Exception ex)
   {
      string Err = ex.Message.ToString();
      EsHelper.EsADLogger("HOQCMgmt.aspx ibtnExcelAll_Click()", ex.Message.ToString());
   }
   finally
   {                
   }
}
c# asp.net
14个回答
156
投票

我在网上研究并发现Response.End()总是抛出异常。

替换这个:HttpContext.Current.Response.End();

有了这个:

HttpContext.Current.Response.Flush(); // Sends all currently buffered output to the client.
HttpContext.Current.Response.SuppressContent = true;  // Gets or sets a value indicating whether to send HTTP content to the client.
HttpContext.Current.ApplicationInstance.CompleteRequest(); // Causes ASP.NET to bypass all events and filtering in the HTTP pipeline chain of execution and directly execute the EndRequest event.

1
投票

这不是问题,但这是设计的。 Microsoft支持页面中描述了根本原因。

Response.End方法结束页面执行并将执行转移到应用程序的事件管道中的Application_EndRequest事件。不执行Response.End之后的代码行。

提供的解决方案是:

对于Response.End,调用HttpContext.Current.ApplicationInstance.CompleteRequest方法而不是Response.End来绕过代码执行到Application_EndRequest事件

这是链接:https://support.microsoft.com/en-us/help/312629/prb-threadabortexception-occurs-if-you-use-response-end--response-redi


0
投票

在response.end()之前刷新对客户端的响应

关于Response.Flush Method的更多信息

所以在response.End();之前使用下面提到的代码

response.Flush();  

0
投票

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

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

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

希望这个答案能帮助别人。这对我有用


0
投票

我找到了原因。如果你删除更新面板,它工作正常!


0
投票

我推荐这个解决方案:

  1. 不要使用response.End();
  2. 声明这个全局var:bool isFileDownLoad;
  3. 就在你的(response.Write(sw.ToString());) set ==> isFileDownLoad = true;之后
  4. 覆盖您的渲染,如: /// AEG : Very important to handle the thread aborted exception override protected void Render(HtmlTextWriter w) { if (!isFileDownLoad) base.Render(w); }

10
投票

这有助于我处理Thread was being aborted异常,

try
{
   //Write HTTP output
    HttpContext.Current.Response.Write(Data);
}  
catch (Exception exc) {}
finally {
   try 
    {
      //stop processing the script and return the current result
      HttpContext.Current.Response.End();
     } 
   catch (Exception ex) {} 
   finally {
        //Sends the response buffer
        HttpContext.Current.Response.Flush();
        // Prevents any other content from being sent to the browser
        HttpContext.Current.Response.SuppressContent = true;
        //Directs the thread to finish, bypassing additional processing
        HttpContext.Current.ApplicationInstance.CompleteRequest();
        //Suspends the current thread
        Thread.Sleep(1);
     }
   }

如果您使用以下代码而不是HttpContext.Current.Response.End(),您将获得Server cannot append header after HTTP headers have been sent异常。

            HttpContext.Current.Response.Flush();
            HttpContext.Current.Response.SuppressContent = True;
            HttpContext.Current.ApplicationInstance.CompleteRequest();

希望能帮助到你


4
投票

看起来是同一个问题:

When an ASP.NET System.Web.HttpResponse.End() is called, the current thread is aborted?

所以它是设计的。您需要为该异常添加一个catch并优雅地“忽略”它。


3
投票

使用特殊的catch块作为Response.End()方法的例外

{
    ...
    context.Response.End(); //always throws an exception

}
catch (ThreadAbortException e)
{
    //this is special for the Response.end exception
}
catch (Exception e)
{
     context.Response.ContentType = "text/plain";
     context.Response.Write(e.Message);
}

或者,如果构建文件处理程序,只需删除Response.End()


2
投票

将Response.End()移动到Try / Catch和Using块之外。

它假设抛出一个Exception来绕过请求的其余部分,你只是不想捕获它。

bool endRequest = false;

try
{
    .. do stuff
    endRequest = true;
}
catch {}

if (endRequest)
    Resonse.End();

2
投票

对我来说只有作品

HttpContext.Current.ApplicationInstance.CompleteRequest()。

https://stackoverflow.com/a/21043051/1828356


1
投票

只是把

Response.End();

在finally块内而不是在try块内。

这对我有用!!!

我有以下问题(使用Exception)代码结构

...
Response.Clear();
...
...
try{
 if (something){
   Reponse.Write(...);
   Response.End();

   return;

 } 

 some_more_code...

 Reponse.Write(...);
 Response.End();

}
catch(Exception){
}
finally{}

它会抛出异常。我怀疑在response.End()之后有代码/工作要执行的地方抛出Exception。 。在我的情况下,额外的代码只是返回本身。

当我刚刚移动了response.End();到finally块(并返回它的位置 - 这导致跳过try块中的其余代码并跳转到finally块(不仅仅是退出包含的函数))Exception不再发生。

以下工作正常:

...
Response.Clear();
...
...
try{
 if (something){
   Reponse.Write(...);

   return;

 } 

 some_more_code...

 Reponse.Write(...);

}
catch(Exception){
}
finally{
    Response.End();
}

1
投票

Response.END()的错误;是因为你正在使用asp更新面板或使用javascript的任何控件,尝试使用asp或html中的控件native而不使用javascript或scriptmanager或脚本并重试


1
投票

我从UpdatePanel中删除了linkbutton,并且还注释了Response.End()成功!

© www.soinside.com 2019 - 2024. All rights reserved.