【问题标题】:How to Avoid Response.End() "Thread was being aborted" Exception during the Excel file downloadExcel 文件下载期间如何避免 Response.End()“线程被中止”异常
【发布时间】:2014-01-26 03:04:37
【问题描述】:

我尝试将我的数据集转换为 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
   {                
   }
}

【问题讨论】:

  • 不要使用Response.Endstackoverflow.com/a/3917180/2864740(和其他答案);请注意,该异常是“可以预料的”,因为它是堆栈展开的方式(因此不要捕获该异常)。如果您仍想捕获 [其他] 异常,请使用:.. catch (ThreadAbortException) { throw; /* propagate */ } catch (Exception ex) { .. }
  • 只是好奇你用的是什么记录器

标签: c# asp.net


【解决方案1】:

我在网上查了一下,发现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.

【讨论】:

  • 哇,天赐之物。它使用 WinDbg 为我节省了数小时的调试时间。就我而言,如果 ThreadAbortException 过多,我的 w3wp.exe 就会崩溃
  • 谢谢。如果您想向 asmx 服务构造函数添加一些授权检查,这段代码真的很有帮助
  • 这对我有用。我用建议的代码替换了 .End() ,现在它可以正常工作了。谢谢,我现在的工作代码是:Response.ContentType = "text/csv"; Response.AddHeader("Content-Disposition",string.Format("attachment;filename=\"{0}\"",Path.GetFileName(filePath))); Response.TransmitFile(filePath); //Response.End(); HttpContext.Current.Response.Flush(); HttpContext.Current.Response.SuppressContent = true; HttpContext.Current.ApplicationInstance.CompleteRequest();
  • 没有。对我不起作用。其实看看答案。如果Response.End() not 有效,为什么建议的答案在最后一行也有Response.End()?相反,@Binny(下)的答案会有所帮助!
  • 根据docs.microsoft.com/en-us/dotnet/api/system.web.httpresponse.end Request.End 的文档,仅支持向后兼容。建议使用 CompleteRequest 作为替代
【解决方案2】:

这有助于我处理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();

希望对你有帮助

【讨论】:

  • 为我工作。以上没有。其实很有趣,虽然Response.End()不起作用,但建议的方法最后一行还有Response.End()
  • 因为您正在捕获并隐藏异常。
  • 多么糟糕的解决方案
【解决方案3】:

看起来与以下问题相同:

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

所以这是设计使然。您需要为该异常添加一个捕获并优雅地“忽略”它。

【讨论】:

  • 我在许多 aspx 屏幕中调用了 public void ExportDataSet(DataSet ds) 函数,并且我还在为运行时引发的异常维护错误记录器方法,这些异常被写入 .txt 文件。所以同样的异常记录在所有aspx屏幕的txt文件中。我只是想避免这个异常从方法声明的类文件抛出到aspx。只是我只想在我的方法声明类文件本身处理这个异常。
  • 根据用户对您问题的评论,只需捕获 TheadAbortException --> catch (ThreadAbortException) { }
  • 是的,在它自己的方法声明类文件中捕获该异常。
【解决方案4】:

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

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

bool endRequest = false;

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

if (endRequest)
    Resonse.End();

【讨论】:

  • 为什么不把它放在 finally 块中,所以它总是被执行?
  • 你可以这样做,特别是如果你在 try 块中有一个 return 语句。但是如果你尝试/捕捉/忽略,那么你甚至不需要finally。重要的是你不应该捕获 ThreadAbortException。
  • 没错,TAE 是返回成功响应的 PITA。
【解决方案5】:

只要放

Response.End();

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

这对我有用!!!。

我有以下有问题(带有异常)的代码结构

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

   return;

 } 

 some_more_code...

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

}
catch(Exception){
}
finally{}

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

当我刚刚移动 response.End();到 finally 块(并将 return 留在原来的位置 - 这导致跳过 try 块中的其余代码并 跳转 到 finally 块(不仅仅是退出包含函数))异常停止发生。

以下工作正常:

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

   return;

 } 

 some_more_code...

 Reponse.Write(...);

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

【讨论】:

    【解决方案6】:

    Response.End() 方法的异常使用特殊的 catch 块

    {
        ...
        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()

    【讨论】:

      【解决方案7】:

      只对我有用

      HttpContext.Current.ApplicationInstance.CompleteRequest()。

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

      【讨论】:

      【解决方案8】:

      我从 UpdatePanel 中删除了链接按钮,并评论了 Response.End() 成功!!!

      【讨论】:

        【解决方案9】:

        Response.END() 的错误;是因为您使用的是 asp 更新面板或任何使用 javascript 的控件,请尝试在没有 javascript 或 scriptmanager 或脚本的情况下使用来自 asp 或 html 的控件本机,然后重试

        【讨论】:

          【解决方案10】:

          这不是问题,但这是设计使然。 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

          【讨论】:

            【解决方案11】:

            我知道,这是一个老问题,但在这里找不到解决方案。 经过一番尝试,我发现,一些添加“

            在(重新)移动它们之后,一切正常。

            【讨论】:

            • 您的答案在一个非常古老的线程上重复了另一个答案。
            • 再看一遍,不是同一个答案,两个不同的原因提到了
            • 它还复制了 2 多年前的以下答案。 “如果您删除更新面板,它会 [sp] 很好!”
            • 啊,好吧,我错过了!对不起。所以我删除了我的第一个条目?? :(
            • 这是您的决定,我认为“正确”的行为是删除重复项,但有时我认为您看到的重复项越多,您就越警惕。干杯。
            【解决方案12】:

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

            更多关于Response.Flush Method

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

            response.Flush();  
            

            【讨论】:

              【解决方案13】:

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

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

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

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

              【讨论】:

              • 虽然它可能有效,但听起来并不是一个可靠的解决方案。你是说防火墙被完全禁用了吗?那将是一个很大的“不”。或者它是为您的应用程序定制的?在数据中心防火墙阻止的东西上看到 ThreadAbortException 也很奇怪……换句话说,不是问题的答案?
              【解决方案14】:

              我找到了原因。如果您删除更新面板,它就可以了!

              【讨论】:

              • 应该在评论中
              【解决方案15】:

              我推荐这个解决方案:

              1. 不要使用response.End();

              2. 声明这个全局变量: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);
                } 
                

              【讨论】:

                【解决方案16】:

                我发现以下方法效果更好......

                   private void EndResponse()
                    {
                        try
                        {
                            Context.Response.End();
                        }
                        catch (System.Threading.ThreadAbortException err)
                        {
                            System.Threading.Thread.ResetAbort();
                        }
                        catch (Exception err)
                        {
                        }
                    }
                

                【讨论】:

                  【解决方案17】:

                  对我来说,注册一个调用代码背后的代码作为回发控件的按钮很有帮助。

                  protected void Page_Init(object sender, EventArgs e)
                  {
                      ScriptManager.GetCurrent(this.Page).RegisterPostBackControl(btnMyExport);
                  }
                  

                  【讨论】:

                    【解决方案18】:
                     My JSON file-download was solved by using the blow code:
                    
                         HttpContext.Current.Response.Flush();
                         HttpContext.Current.Response.SuppressContent = true;
                         HttpContext.Current.ApplicationInstance.CompleteRequest();
                    
                     But Excel file-download was solved by the below way:
                    
                     try {
                          .....
                         }
                            catch (System.IO.IOException iex)
                            {
                                throw (iex);
                            }
                            catch (System.Threading.ThreadAbortException)
                            {
                                throw new Exception("ABORTED");//make a custom msg here and catch it 
                                                               //where required to continue the rest 
                                                               //of the work flow.
                            }
                            catch (Exception exx)
                            {
                                throw (exx);
                            }
                            finally
                            {
                               ....
                            }
                    

                    【讨论】:

                      猜你喜欢
                      • 2013-07-07
                      • 2014-01-20
                      • 1970-01-01
                      • 2012-12-26
                      • 2012-09-20
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多