Excel 파일 다운로드 중 Response.End () "스레드가 중단되었습니다"예외를 방지하는 방법


96

내 데이터 세트를 Excel로 변환하고 해당 Excel을 다운로드하려고했습니다. 필요한 Excel 파일을 얻었지만 System.Threading.ThreadAbortException이 모든 Excel 다운로드에서 발생했습니다. 이 문제를 해결하는 방법? .. 도와주세요 ...

내 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
   {                
   }
}

2
사용하지 마십시오. stackoverflow.com/a/3917180/2864740 (및 기타 답변)을 Response.End참조하십시오 . 예외는 스택이 풀리는 방식이므로 "예상되는"것입니다 (그러므로 예외를 포착하지 마십시오). [기타] 예외를 포착하려면 다음을 사용하십시오... catch (ThreadAbortException) { throw; /* propagate */ } catch (Exception ex) { .. }
user2864740

그냥 호기심에서 어떤 로거 사용한다는 것입니다
rogue39nin

답변:


195

온라인으로 조사한 결과 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.

2
와우 신의 선물. WinDbg를 사용하여 디버그 시간을 절약했습니다. 내 경우에는, 내 W3wp.exe를가 너무 많은 ThreadAbortException이있는 경우 추락
디오 Phung에게

감사. 이 코드는 asmx 서비스 생성자에 인증 검사를 추가하려는 경우 매우 유용합니다
vadim

이것은 나를 위해 일했습니다. .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 ();
Nour Lababidi

3
아니요. 저에게는 효과가 없습니다. 사실 답을보세요. 작동 Response.End()하지 않는 경우 제안 된 답변이 Response.End()마지막 줄 에도 있는 이유는 무엇입니까? 대신 @Binny (아래)의 답변이 도움이됩니다!
user3454439 jul.

1
docs.microsoft.com/en-us/dotnet/api/system.web.httpresponse.end의 설명서에 따르면 Request.End는 이전 버전과의 호환성을 위해서만 지원됩니다. CompleteRequest 사용은 대체 추천
루돌프 Dvoracek을

11

이것은 제가 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();

도움이되기를 바랍니다.


1
나를 위해 작동합니다. 위는 그렇지 않습니다. 실제로 Response.End()작동하지 않는 동안 재미 있지만 제안 된 방법은 Response.End()마지막 줄에도 있습니까?
user3454439 jul.

1
예외를 포착하고 숨기고 있기 때문입니다.
Dan Friedman

3
얼마나 끔찍한 솔루션
Razor

4

다음과 같은 질문으로 보입니다.

ASP.NET System.Web.HttpResponse.End ()가 호출되면 현재 스레드가 중단됩니까?

그래서 그것은 의도적으로 설계된 것입니다. 해당 예외에 대한 catch를 추가하고 우아하게 "무시"해야합니다.


많은 aspx 화면에서 public void ExportDataSet (DataSet ds) 함수를 호출하고 런타임시 발생하는 예외에 대한 오류 로거 메서드를 유지 관리하고 있습니다. 해당 예외가 .txt 파일에 기록됩니다. 따라서 동일한 예외가 모든 aspx 화면의 txt 파일에 기록됩니다. 메서드 선언 클래스 파일에서 aspx로 예외가 발생하는 것을 방지하고 싶습니다. 단순히 메서드 선언 클래스 파일 자체에서이 예외를 처리하고 싶습니다.
user3171957

질문에 대한 사용자의 의견에 따라 TheadAbortException-> catch (ThreadAbortException) {}
robnick

예 메서드 선언 클래스 파일에서 예외를 잡아냅니다.
user3171957

4

Response.End ()를 Try / Catch 및 Using 블록 외부로 이동합니다.

나머지 요청을 우회하기 위해 Exception을 던진다 고 가정하고, 당신은 그것을 잡을 것이라고 가정하지 않았습니다.

bool endRequest = false;

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

if (endRequest)
    Resonse.End();

마지막 블록에 배치하면 항상 실행됩니다.
GoldBishop 2017 년

특히 try 블록에 return 문이있는 경우 그렇게 할 수 있습니다. 그러나 시도 / 잡기 / 무시하면 마침내 필요하지 않습니다. 중요한 것은 ThreadAbortException을 잡아서는 안된다는 것입니다.
Steve

사실, TAE는 성공적인 응답을 반환하기위한 PITA입니다.
GoldBishop 2017 년

3

그냥 넣어

Response.End();

마침내try 블록이 아닌 블록 내에 있습니다.

이것은 나를 위해 일했습니다 !!!.

다음과 같은 문제가 있습니다 (예외) 코드 구조

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

   return;

 } 

 some_more_code...

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

}
catch(Exception){
}
finally{}

예외가 발생합니다. 나는 response.End () 후에 실행할 코드 / 작업이있는 곳에서 예외가 발생한다고 생각합니다. . 제 경우에는 추가 코드가 반환 자체였습니다.

방금 응답을 옮겼을 때 .End (); finally 블록으로 (그리고 그 자리에 리턴을 남겨 두었습니다. 이로 인해 try 블록의 나머지 코드를 건너 뛰고 점프합니다. finally 블록으로 합니다 (포함 함수를 종료하지 않음)) Exception 발생이 중단되었습니다.

다음은 정상적으로 작동합니다.

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

   return;

 } 

 some_more_code...

 Reponse.Write(...);

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

3

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 ()를 제거하십시오.




1

Response.END (); 오류 ASP 업데이트 패널이나 자바 스크립트를 사용하는 컨트롤을 사용하고 있기 때문입니다. 자바 스크립트 나 스크립트 관리자 또는 스크립팅없이 asp 또는 html에서 네이티브 컨트롤을 사용하고 다시 시도하세요.


1

이것은 문제가 아니지만 의도적으로 설계된 것입니다. 근본 원인은 Microsoft 지원 페이지에 설명되어 있습니다.

Response.End 메서드는 페이지 실행을 종료하고 응용 프로그램의 이벤트 파이프 라인에서 Application_EndRequest 이벤트로 실행을 이동합니다. Response.End 뒤에 오는 코드 줄은 실행되지 않습니다.

제공되는 솔루션은 다음과 같습니다.

Response.End의 경우 Response.End 대신 HttpContext.Current.ApplicationInstance.CompleteRequest 메서드를 호출하여 코드 실행을 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 메서드 에 대한 추가 정보

따라서 아래에 언급 된 코드를 사용하십시오. response.End();

response.Flush();  

0

위의 모든 변경 사항을 사용했지만 여전히 웹 응용 프로그램에서 동일한 문제가 발생했습니다.

그런 다음 호스팅 제공 업체에 연락하여 HTTP를 통해 파일 전송을 차단하는 소프트웨어 또는 바이러스 백신이 있는지 확인하도록 요청했습니다. 또는 ISP / 네트워크가 파일 전송을 허용하지 않습니다.

그들은 서버 설정을 확인하고 내 서버에 대한 "데이터 센터 공유 방화벽"을 우회했으며 이제 응용 프로그램에서 파일을 다운로드 할 수 있습니다.

이 답변이 누군가를 도울 수 있기를 바랍니다.


작동 할 수는 있지만 견고한 솔루션으로 들리지는 않습니다. 방화벽이 완전히 비활성화되어 있습니까? 그것은 큰 "아니오"입니다. 아니면 응용 프로그램에 맞게 사용자 정의 되었습니까? 또한 데이터 센터 방화벽이 차단하는 것에 대해 ThreadAbortException을 보는 것이 이상합니다. 즉, 질문에 대한 답이 아닙니까?
Michael


0

이 솔루션을 권장합니다.

  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);
    } 

0

다음이 더 잘 작동한다는 것을 알았습니다.

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

0

저에게는 포스트 백 컨트롤로 코드 뒤의 코드를 호출하는 버튼을 등록하는 데 도움이되었습니다.

protected void Page_Init(object sender, EventArgs e)
{
    ScriptManager.GetCurrent(this.Page).RegisterPostBackControl(btnMyExport);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.