Context.Response.End()和Thread正在中止

时间:2023-01-25 21:00:12

I am trying to close the response using Context.Response.End but receive error "Thread was being aborted".

我试图使用Context.Response.End关闭响应,但收到错误“线程被中止”。

How do I correctly close the response without triggering an exception?

如何在不触发异常的情况下正确关闭响应?

try {
   Context.Response.Clear();
   Context.Response.ContentType = "text/html"; 
   //Context.Response.ContentType = "application/json";
   JsonObjectCollection collection = new JsonObjectCollection();
   collection.Add(new JsonNumericValue("resultcode", 1));
   collection.Add(new JsonStringValue("sourceurl", exchangeData.cUrl));
   collection.Add(new JsonStringValue("filename", fileName));
   collection.Add(new JsonStringValue("filesize", fileSize));
   collection.Add(new JsonStringValue("fileurl", Common.GetPDFURL + outputFileName));
   JsonUtility.GenerateIndentedJsonText = true;
   Context.Response.Write(collection);
  try {
     Context.Response.End();
  } catch (ThreadAbortException exc) {
     // This should be first catch block i.e. before generic Exception
     // This Catch block is to absorb exception thrown by Response.End
  }
} catch (Exception err) {

}

Solved by myself, the code should look like

由我自己解决,代码应该看起来像

try {
  Context.Response.End();
} catch (ThreadAbortException err) {

}
catch (Exception err) {
}

6 个解决方案

#1


26  

Is there a specific reason you aren't using context.ApplicationInstance.CompleteRequest() instead?

您是否有特定原因未使用context.ApplicationInstance.CompleteRequest()?

This method will short circuit the ASP.NET pipeline (except for the EndRequest event) without throwing the ThreadAbortException so you won't need the extra try/catch block, and you will also experience better performance.

此方法将短路ASP.NET管道(EndRequest事件除外)而不抛出ThreadAbortException,因此您不需要额外的try / catch块,您也将体验到更好的性能。

#2


7  

Try response.OutputStream.Close(); instead of response.End(); It will help!

尝试response.OutputStream.Close();而不是response.End();我会帮你的!

#3


2  

Error: Thread was being aborted. at System.Threading.Thread.AbortInternal() at System.Threading.Thread.Abort(Object stateInfo) at System.Web.HttpResponse.End()

错误:线程正在中止。 System.Web.HttpResponse.End()上的System.Threading.Thread.Abort(Object stateInfo)中的System.Threading.Thread.AbortInternal()

This error occurs mainly If You Use Response.End, Response.Redirect, or Server.Transfer

发生此错误主要是因为您使用Response.End,Response.Redirect或Server.Transfer

Cause: The Response.End method ends the page execution and shifts the execution to the Application_EndRequest event in the application’s event pipeline. The line of code that follows Response.End is not executed.

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

This problem occurs in the Response.Redirect and Server.Transfer methods because both methods call Response.End internally.

Response.Redirect和Server.Transfer方法中会出现此问题,因为两个方法都在内部调用Response.End。

Resolution/Solution:

分辨率/解决方案:

You can use a try-catch statement to catch this exception

您可以使用try-catch语句来捕获此异常

or

要么

For Response.End, call the HttpContext.Current.ApplicationInstance.CompleteRequest method instead of Response.End to bypass the code execution to the Application_EndRequest event. For Response.Redirect, use an overload, Response.Redirect(String url, bool endResponse) that passes false for the endResponse parameter to suppress the internal call to Response.End. For example: ex: Response.Redirect (“nextpage.aspx”, false); If you use this workaround, the code that follows Response.Redirect is executed. For Server.Transfer, use the Server.Execute method instead.

对于Response.End,调用HttpContext.Current.ApplicationInstance.CompleteRequest方法而不是Response.End来绕过代码执行到Application_EndRequest事件。对于Response.Redirect,使用一个重载,Response.Redirect(String url,bool endResponse),它为endResponse参数传递false以禁止对Response.End的内部调用。例如:ex:Response.Redirect(“nextpage.aspx”,false);如果使用此解决方法,则会执行Response.Redirect之后的代码。对于Server.Transfer,请改用Server.Execute方法。

#4


0  

I recommend this solution :

我推荐这个解决方案:

  1. Don't use response.End();

    不要使用response.End();

  2. Declare this global var : bool isFileDownLoad;

    声明这个全局var:bool isFileDownLoad;

  3. Just after your (response.Write(sw.ToString());) set ==> isFileDownLoad = true;

    就在你的(response.Write(sw.ToString());)set ==> isFileDownLoad = true之后;

  4. Override your Render like :

    覆盖您的渲染,如:

    /// /// AEG : Very important to handle the thread aborted exception /// /// override protected void Render(HtmlTextWriter w) { if (!isFileDownLoad) base.Render(w); }

    /// /// AEG:处理线程中止异常非常重要/// //覆盖protected void Render(HtmlTextWriter w){if(!isFileDownLoad)base.Render(w); }

#5


0  

Or you can place the context.Response.End() inside a finally bloc. That way you won't have to care about undesired ThreadAbortException, nor ignore real ThreadAbortException (which is bad). You also won't ignore pipeline stages.

或者您可以将context.Response.End()放在finally bloc中。这样你就不必关心不受欢迎的ThreadAbortException,也不会忽略真正的ThreadAbortException(这很糟糕)。您也不会忽略管道阶段。

try
{
    context.Response.ContentType = "application/json";
    context.Response.ContentEncoding = Encoding.UTF8;

    if (NotAuthorized())
    {
        context.Response.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
        return;
    }

    context.Response.Write(MakeJsonStuff());
}
catch (Exception ex)
{
    LogException(ex);

    context.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
    context.Response.Write(MakeJsonError(ex));
}
finally
{
    context.Response.End();
}

#6


0  

This helped me to handle Thread was being aborted exception,

这有助于我处理Thread被中止异常,

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

if you use the following the following code instead of HttpContext.Current.Response.End() , you will get Server cannot append header after HTTP headers have been sent exception.

如果您使用以下代码而不是HttpContext.Current.Response.End(),您将获得在HTTP标头发送异常后服务器无法追加标头。

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

Another Fix which I found is Thread.BeginCriticalRegion();

我发现的另一个修复是Thread.BeginCriticalRegion();

   try 
 {
    //Write HTTP output
   HttpContext.Current.Response.Write(Data);
  } catch (Exception exc) {} 
  finally {
    try {
     //Notifies a host that execution is about to enter a region of code in which the effects of a thread abort or unhandled exception might jeopardize other tasks in the application domain.
     Thread.BeginCriticalRegion();
     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();
    Thread.EndCriticalRegion();
         }
   }

Hope it helps

希望能帮助到你

#1


26  

Is there a specific reason you aren't using context.ApplicationInstance.CompleteRequest() instead?

您是否有特定原因未使用context.ApplicationInstance.CompleteRequest()?

This method will short circuit the ASP.NET pipeline (except for the EndRequest event) without throwing the ThreadAbortException so you won't need the extra try/catch block, and you will also experience better performance.

此方法将短路ASP.NET管道(EndRequest事件除外)而不抛出ThreadAbortException,因此您不需要额外的try / catch块,您也将体验到更好的性能。

#2


7  

Try response.OutputStream.Close(); instead of response.End(); It will help!

尝试response.OutputStream.Close();而不是response.End();我会帮你的!

#3


2  

Error: Thread was being aborted. at System.Threading.Thread.AbortInternal() at System.Threading.Thread.Abort(Object stateInfo) at System.Web.HttpResponse.End()

错误:线程正在中止。 System.Web.HttpResponse.End()上的System.Threading.Thread.Abort(Object stateInfo)中的System.Threading.Thread.AbortInternal()

This error occurs mainly If You Use Response.End, Response.Redirect, or Server.Transfer

发生此错误主要是因为您使用Response.End,Response.Redirect或Server.Transfer

Cause: The Response.End method ends the page execution and shifts the execution to the Application_EndRequest event in the application’s event pipeline. The line of code that follows Response.End is not executed.

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

This problem occurs in the Response.Redirect and Server.Transfer methods because both methods call Response.End internally.

Response.Redirect和Server.Transfer方法中会出现此问题,因为两个方法都在内部调用Response.End。

Resolution/Solution:

分辨率/解决方案:

You can use a try-catch statement to catch this exception

您可以使用try-catch语句来捕获此异常

or

要么

For Response.End, call the HttpContext.Current.ApplicationInstance.CompleteRequest method instead of Response.End to bypass the code execution to the Application_EndRequest event. For Response.Redirect, use an overload, Response.Redirect(String url, bool endResponse) that passes false for the endResponse parameter to suppress the internal call to Response.End. For example: ex: Response.Redirect (“nextpage.aspx”, false); If you use this workaround, the code that follows Response.Redirect is executed. For Server.Transfer, use the Server.Execute method instead.

对于Response.End,调用HttpContext.Current.ApplicationInstance.CompleteRequest方法而不是Response.End来绕过代码执行到Application_EndRequest事件。对于Response.Redirect,使用一个重载,Response.Redirect(String url,bool endResponse),它为endResponse参数传递false以禁止对Response.End的内部调用。例如:ex:Response.Redirect(“nextpage.aspx”,false);如果使用此解决方法,则会执行Response.Redirect之后的代码。对于Server.Transfer,请改用Server.Execute方法。

#4


0  

I recommend this solution :

我推荐这个解决方案:

  1. Don't use response.End();

    不要使用response.End();

  2. Declare this global var : bool isFileDownLoad;

    声明这个全局var:bool isFileDownLoad;

  3. Just after your (response.Write(sw.ToString());) set ==> isFileDownLoad = true;

    就在你的(response.Write(sw.ToString());)set ==> isFileDownLoad = true之后;

  4. Override your Render like :

    覆盖您的渲染,如:

    /// /// AEG : Very important to handle the thread aborted exception /// /// override protected void Render(HtmlTextWriter w) { if (!isFileDownLoad) base.Render(w); }

    /// /// AEG:处理线程中止异常非常重要/// //覆盖protected void Render(HtmlTextWriter w){if(!isFileDownLoad)base.Render(w); }

#5


0  

Or you can place the context.Response.End() inside a finally bloc. That way you won't have to care about undesired ThreadAbortException, nor ignore real ThreadAbortException (which is bad). You also won't ignore pipeline stages.

或者您可以将context.Response.End()放在finally bloc中。这样你就不必关心不受欢迎的ThreadAbortException,也不会忽略真正的ThreadAbortException(这很糟糕)。您也不会忽略管道阶段。

try
{
    context.Response.ContentType = "application/json";
    context.Response.ContentEncoding = Encoding.UTF8;

    if (NotAuthorized())
    {
        context.Response.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
        return;
    }

    context.Response.Write(MakeJsonStuff());
}
catch (Exception ex)
{
    LogException(ex);

    context.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
    context.Response.Write(MakeJsonError(ex));
}
finally
{
    context.Response.End();
}

#6


0  

This helped me to handle Thread was being aborted exception,

这有助于我处理Thread被中止异常,

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

if you use the following the following code instead of HttpContext.Current.Response.End() , you will get Server cannot append header after HTTP headers have been sent exception.

如果您使用以下代码而不是HttpContext.Current.Response.End(),您将获得在HTTP标头发送异常后服务器无法追加标头。

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

Another Fix which I found is Thread.BeginCriticalRegion();

我发现的另一个修复是Thread.BeginCriticalRegion();

   try 
 {
    //Write HTTP output
   HttpContext.Current.Response.Write(Data);
  } catch (Exception exc) {} 
  finally {
    try {
     //Notifies a host that execution is about to enter a region of code in which the effects of a thread abort or unhandled exception might jeopardize other tasks in the application domain.
     Thread.BeginCriticalRegion();
     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();
    Thread.EndCriticalRegion();
         }
   }

Hope it helps

希望能帮助到你