【问题标题】:ThreadAbortException handling in asp.net while executing Response.End() method执行 Response.End() 方法时在 asp.net 中处理 ThreadAbortException
【发布时间】:2014-01-10 11:16:03
【问题描述】:

在 asp.net 中执行 Response.End(); 方法时,它会抛出我在 catch 块中处理的 ThreadAbortException,在内部 catch 块结束后,我想执行一些进一步的代码,但它直接跳转到外部 catch 块。这是因为响应已经结束并且 .net 框架没有执行任何进一步的代码吗?

protected void btn_click(object sender, EventArgs e)
{

    try
    {
        string fileToDownload = MapPath(@"~\Sample.txt");
        string fileToRead = MapPath(@"~\FileNotExist.txt");

        try
        {
            //Section 1
            try
            { 
                // try to read the file which does not exist to raise the exception
                StreamReader ss = new StreamReader(fileToRead);
            }
            catch (IOException IoEx)
            {
                // Just for sample exception
            }

            // Section 2 code block still execute because exception handled by upper try catch block 
            //Section 2

            Response.Clear();
            Response.ClearHeaders();
            Response.AddHeader("Content-Disposition", "attachment;filename=SampleTemplate.txt");
            Response.ContentType = "text";
            Response.WriteFile(fileToDownload);
            Response.Flush();
            Response.End();

        }
        catch (System.Threading.ThreadAbortException abrtEx)
        {
          // do not treat this exception as Exception
        }

        //Section 3 Code block not executing even after exception handeled by ThreadAbortException 
        //Section 3
         string test = "Do futher process after sample downloaded";


    }
    catch (Exception ex) // Outer Catch Block
    {
        throw ex;
    }


}

【问题讨论】:

  • “样本下载后进行进一步处理”应该做什么?页面将完成其任务(提供下载文件。您希望它接下来做什么?
  • @Alexander:我只发布了我创建来解释我的场景的示例代码,真正的代码在下载之前和下载之后做了很多事情,我已经在我想要的 catch 块下完成了我们的 after doenload 代码纠正并移出捕获块。
  • 我想了很多,是的,但我问的原因是我担心你使用页面生命周期错误。因此,对我来说,这是一个重要的问题。对于主页,在您结束响应后,它的生命就结束了。
  • 是的,我明白了,但是在下载与页面生命周期无关的代码后,它会激活/停用某些服务并编写从其他来源收到的一些内容。我有其他解决方法,但首先我会尝试更正代码,如果可以的话

标签: c# asp.net .net


【解决方案1】:

代替

Response.End()

使用

HttpContext.Current.ApplicationInstance.CompleteRequest()

这样

protected void btn_click(object sender, EventArgs e)
{
    try
    {
        string fileToDownload = MapPath(@"~\Sample.txt");
        string fileToRead = MapPath(@"~\FileNotExist.txt");

        try
        {
            //Section 1
            try
            { 
                // try to read the file which does not exist to raise the exception
                StreamReader ss = new StreamReader(fileToRead);
            }
            catch (IOException IoEx)
            {
                // Just for sample exception
            }

            // Section 2 code block still execute because exception handled by upper try catch block 
            //Section 2

            Response.Clear();
            Response.ClearHeaders();
            Response.AddHeader("Content-Length", fileToDownload.Length.ToString()); 
            Response.AddHeader("Content-Disposition","attachment;filename=SampleTemplate.txt");
            Response.ContentType = "text";
            Response.WriteFile(fileToDownload);
            Response.Flush();
            HttpContext.Current.ApplicationInstance.CompleteRequest();

        }
        catch (System.Threading.ThreadAbortException abrtEx)
        {

        }

        //Section 3 Code block not executing even after exception handeled by ThreadAbortException 
        //Section 3
         string test = "Do futher process after sample downloaded";


    }
    catch (Exception ex) // Outer Catch Block
    {
        throw ex;
    }
}

【讨论】:

  • 您的解决方案也可以正常工作,但“Sample.txt”文件内容正在使用页面 apsx 内容进行编辑
  • 一些额外的内容会自动添加到我的 Sample.txt 文件中,这看起来像是页面 aspx 代码。我的 Sample.txt 文件只有“名称######## ID ######## DateDone”,但下载后包含“名称######## ID ###### ## DateDone" ; ; ..... . .... –
  • 您好,您需要为内容长度添加附加标题。我已经更新了解决方案。请检查一下。我也有同样的问题。请参考这里 stackoverflow.com/questions/20605705/getting-unwanted-output-when-using-response-binarywritemybyte-and-context-appl
  • @VigneshKumar 在您的示例文件中ToDownload.Length 将返回带有路径的字符串变量的长度,而不是内容的长度
【解决方案2】:

根据PRB: ThreadAbortException Occurs If You Use Response.End, Response.Redirect, or Server.Transfer

如果您使用 Response.EndResponse.RedirectServer.Transfer 方法,发生ThreadAbortException 异常。您可以使用 try-catch 语句来捕获此异常。

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

此问题发生在 Response.RedirectServer.Transfer 方法,因为这两种方法都在内部调用 Response.End。

解决这个问题

,使用以下方法之一:

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

对于 Response.Redirect,使用重载 Response.Redirect(String url, bool endResponse) 为 endResponse 传递 false 参数来抑制对 Response.End 的内部调用。为了 示例:Response.Redirect("nextpage.aspx", false); 如果您使用此解决方法,则会执行 Response.Redirect 之后的代码。

对于 Server.Transfer,请改用 Server.Execute 方法。

此行为是设计使然。

【讨论】:

    【解决方案3】:

    这是因为您没有在 catch 块中调用 Thread.ResetAbort。没有它,CLR 将不会继续执行此方法。所以你的代码应该是:

    try
    {
       ...
    }
    catch (System.Threading.ThreadAbortException abrtEx)
    {
       Thread.ResetAbort();
    }
    

    但这不是一个好习惯。你可以在这里阅读为什么它是有害的 - Is Response.End() considered harmful?

    你可以完成你的逻辑,然后在它调用Response.End()之后,而不是在方法中间

    【讨论】:

    • 它的工作但“Sample.txt”文件内容正在使用页面 apsx 内容进行编辑
    • 一些额外的内容会自动添加到我的 Sample.txt 文件中,这看起来像是页面 aspx 代码。我的 Sample.txt 文件只有“名称######## ID ######## DateDone”,但下载后包含“名称######## ID ###### ## DateDone" ttp://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" rel="nofollow" target="_blank">w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> w3.org/1999/xhtml"> ...... . ....
    猜你喜欢
    • 2011-08-19
    • 1970-01-01
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-30
    相关资源
    最近更新 更多