簡體   English   中英

如何避免 Response.End() “線程被中止” Excel 文件下載期間的異常

[英]How to Avoid Response.End() "Thread was being aborted" Exception during the Excel file download

我試圖將我的數據集轉換為 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.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.

這幫助我處理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();

希望它有幫助

看起來與以下問題相同:

當 ASP.NET System.Web.HttpResponse.End() 被調用時,當前線程被中止?

所以這是設計使然。 您需要為該異常添加一個捕獲並優雅地“忽略”它。

將 Response.End() 移到 Try/Catch 和 Using 塊之外。

假設拋出異常以繞過請求的其余部分,您只是不應該捕獲它。

bool endRequest = false;

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

if (endRequest)
    Resonse.End();

只要把

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 塊(並將返回留在其位置 - 這導致跳過 try 塊中的其余代碼並跳轉到 finally 塊(不僅僅是退出包含函數))異常停止發生。

以下工作正常:

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

   return;

 } 

 some_more_code...

 Reponse.Write(...);

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

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

對我來說只有效

HttpContext.Current.ApplicationInstance.CompleteRequest()。

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

我從 UpdatePanel 中刪除了鏈接按鈕,並評論了 Response.End() 成功!!!

Response.END() 的錯誤; 是因為您使用的是 asp 更新面板或任何使用 javascript 的控件,請嘗試使用來自 asp 或 html 的控件,而不使用 javascript 或腳本管理器或腳本,然后再試一次

這不是問題,但這是設計使然。 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

我知道,這是一個老問題,但在這里找不到解決方案。 經過一些嘗試,我發現,一些添加了“<asp:UpdatePanel”是原因。

在(重新)移動它們之后,一切都像以前一樣正常。

我推薦這個解決方案:

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

  2. 聲明這個全局bool isFileDownLoad;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); }

在 response.end() 之前刷新對客戶端的響應

更多關於Response.Flush 方法

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

response.Flush();  

我使用了上述所有更改,但仍然在我的 Web 應用程序上遇到相同的問題。

然后我聯系了我的托管服務提供商並要求他們檢查是否有任何軟件或防病毒軟件阻止了我們的文件通過 HTTP 傳輸。 或 ISP/網絡不允許文件傳輸。

他們檢查了服務器設置並繞過了我服務器的“數據中心共享防火牆”,現在我們的應用程序可以下載該文件。

希望這個答案能幫助某人。這對我有用

我找到了原因。 如果您刪除更新面板,它會很好!

我發現以下效果更好......

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

對我來說,它有助於注冊一個按鈕,該按鈕將代碼背后的代碼調用為回發控件。

protected void Page_Init(object sender, EventArgs e)
{
    ScriptManager.GetCurrent(this.Page).RegisterPostBackControl(btnMyExport);
}
 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
        {
           ....
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM