So vermeiden Sie Response.End () Ausnahme "Thread wurde abgebrochen" Ausnahme beim Herunterladen der Excel-Datei

96

Ich habe versucht, mein Dataset in Excel zu konvertieren und dieses Excel herunterzuladen. Ich habe meine erforderliche Excel-Datei erhalten. Aber System.Threading.ThreadAbortException wurde bei jedem Excel-Download ausgelöst. Wie kann ich dieses Problem beheben? .. Bitte helfen Sie mir ...

Ich rufe diese Methode in meinem Aspx-Bildschirm auf. Es gibt auch dieselbe Ausnahme, die von dieser Methode ausgelöst wurde.

Ich nenne diese öffentliche void ExportDataSet (DataSet ds) -Funktion in vielen Aspx-Bildschirmen und behalte auch die Fehlerprotokollierungsmethode für Ausnahmen bei, die zur Laufzeit ausgelöst werden, wenn diese Ausnahmen in eine TXT-Datei geschrieben werden. Daher wird dieselbe Ausnahme in allen txt-Dateien des Aspx-Bildschirms protokolliert. Ich möchte nur vermeiden, dass diese Ausnahme von einer von der Methode deklarierten Klassendatei zu Aspx ausgelöst wird. Ich möchte diese Ausnahme einfach nur in meiner Methodendeklarationsklassendatei selbst behandeln.

Aufruf der ASPX-Dateimethode: excel.ExportDataSet (dsExcel);

Methodendefinition:

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
   {                
   }
}
user3171957
quelle
2
Verwenden Sie nicht Response.Endsiehe stackoverflow.com/a/3917180/2864740 (und die anderen Antworten); Beachten Sie, dass die Ausnahme "zu erwarten" ist, da der Stapel so abgewickelt wird (fangen Sie diese Ausnahme also nicht ab). Wenn Sie immer noch [andere] Ausnahmen abfangen möchten, verwenden Sie:.. catch (ThreadAbortException) { throw; /* propagate */ } catch (Exception ex) { .. }
user2864740
Nur aus Neugier, was für ein Logger Sie verwenden
rogue39nin

Antworten:

193

Ich habe online recherchiert und festgestellt, dass das Response.End()immer eine Ausnahme auslöst.

Ersetzen Sie dies: HttpContext.Current.Response.End();

Mit diesem:

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.
user3412640
quelle
2
Wow ein Glücksfall. Es hat mir Stunden beim Debuggen mit WinDbg erspart. In meinem Fall stürzte meine w3wp.exe gerade ab, wenn es zu viele ThreadAbortException gibt
Dio Phung
Vielen Dank. Dieser Code ist wirklich hilfreich, wenn Sie dem asmx-Servicekonstruktor
vadim
Das hat bei mir funktioniert. Ich habe .End () durch den vorgeschlagenen Code ersetzt und es funktioniert jetzt ausnahmslos. Vielen Dank, mein Arbeitscode lautet jetzt: Response.ContentType = "text / csv"; Response.AddHeader ("Content-Disposition", string.Format ("Anhang; Dateiname =" {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
Funktioniert bei mir nicht. Schauen Sie sich die Antwort an. Wenn Response.End()dies nicht funktioniert, warum steht die vorgeschlagene Antwort auch Response.End()in der letzten Zeile? Stattdessen hilft die Antwort von @Binny (unten)!
user3454439
1
Gemäß der Dokumentation unter docs.microsoft.com/en-us/dotnet/api/system.web.httpresponse.end wird Request.End nur aus Gründen der Abwärtskompatibilität unterstützt. Die Verwendung von CompleteRequest wird als Ersatz empfohlen
Rudolf Dvoracek
11

Dies hat mir geholfen, mit Thread was being abortedAusnahmen umzugehen .

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

Wenn Sie anstelle des folgenden Codes den folgenden Code verwenden HttpContext.Current.Response.End(), erhalten Sie eine Server cannot append header after HTTP headers have been sentAusnahme.

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

Ich hoffe es hilft

Binny
quelle
1
Funktioniert bei mir. Das obige nicht. Eigentlich ist es lustig, dass das Response.End()zwar nicht funktioniert, aber die vorgeschlagene Methode auch Response.End()in der letzten Zeile steht?
user3454439
1
Weil Sie die Ausnahme abfangen und ausblenden.
Dan Friedman
3
Was für eine schreckliche Lösung
Razor
4

Scheint die gleiche Frage zu sein wie:

Wenn ein ASP.NET System.Web.HttpResponse.End () aufgerufen wird, wird der aktuelle Thread abgebrochen?

Es ist also beabsichtigt. Sie müssen einen Haken für diese Ausnahme hinzufügen und ihn ordnungsgemäß "ignorieren".

Robnick
quelle
Ich nenne diese öffentliche void ExportDataSet (DataSet ds) -Funktion in vielen Aspx-Bildschirmen und behalte auch die Fehlerprotokollierungsmethode für Ausnahmen bei, die zur Laufzeit ausgelöst werden, wenn diese Ausnahmen in eine TXT-Datei geschrieben werden. Daher wird dieselbe Ausnahme in allen txt-Dateien des Aspx-Bildschirms protokolliert. Ich möchte nur vermeiden, dass diese Ausnahme von einer von der Methode deklarierten Klassendatei zu Aspx ausgelöst wird. Ich möchte diese Ausnahme einfach nur in meiner Methodendeklarationsklassendatei selbst behandeln.
user3171957
Pro Kommentar des Benutzers in Ihrer Frage fangen Sie einfach die TheadAbortException -> catch (ThreadAbortException) {}
robnick
Ja, fangen Sie diese Ausnahme mit der Methodendeklarationsklassendatei selbst ab.
user3171957
4

Verschieben Sie Response.End () außerhalb der Try / Catch- und Using-Blöcke.

Es wird angenommen, dass Sie eine Ausnahme auslösen, um den Rest der Anforderung zu umgehen. Sie sollten sie nur nicht abfangen.

bool endRequest = false;

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

if (endRequest)
    Resonse.End();
Steve
quelle
Warum platzieren Sie das nicht in einem finally-Block, damit es immer ausgeführt wird?
GoldBishop
Sie können dies tun, insbesondere wenn Sie eine return-Anweisung im try-Block haben. Aber wenn Sie versuchen / fangen / ignorieren, brauchen Sie nicht einmal das endgültige. Wichtig ist, dass Sie die ThreadAbortException nicht abfangen.
Steve
Die TAE ist zwar eine PITA für die Rückgabe einer erfolgreichen Antwort.
GoldBishop
3

Setzen Sie einfach die

Response.End();

innerhalb eines finally- Blocks anstelle des try-Blocks.

Das hat bei mir geklappt !!!.

Ich hatte die folgende problematische (mit der Ausnahme) Codestruktur

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

   return;

 } 

 some_more_code...

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

}
catch(Exception){
}
finally{}

und es löst die Ausnahme aus. Ich vermute, dass die Ausnahme ausgelöst wird, wenn nach der Antwort Code / Arbeit ausgeführt werden muss.End (); . In meinem Fall war der zusätzliche Code nur die Rückgabe selbst.

Als ich gerade die Antwort verschoben habe.End (); Für den finally-Block (und die Rückgabe an ihrer Stelle belassen - was dazu führt, dass der Rest des Codes im try-Block übersprungen wird und zum finally-Block gesprungen wird (nicht nur die enthaltende Funktion verlassen)) wurde die Ausnahme nicht mehr ausgeführt.

Folgendes funktioniert OK:

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

   return;

 } 

 some_more_code...

 Reponse.Write(...);

}
catch(Exception){
}
finally{
    Response.End();
}
user2265251
quelle
3

Verwenden Sie einen speziellen catch-Block für die Ausnahme der Response.End () -Methode

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

Oder entfernen Sie einfach Response.End (), wenn Sie einen Dateihandler erstellen

SoliQuiD
quelle
2

Ich habe den Linkbutton aus dem UpdatePanel entfernt und auch den Response.End () Success kommentiert !!!

Nunopacheco
quelle
1

der Fehler für Response.END (); Weil Sie ein Asp-Update-Panel oder ein Steuerelement verwenden, das Javascript verwendet, versuchen Sie, ein natives Steuerelement aus Asp oder HTML ohne Javascript oder Scriptmanager oder Scripting zu verwenden, und versuchen Sie es erneut

Ivan Renteria Vidal
quelle
1

Dies ist kein Problem, aber dies ist beabsichtigt. Die Hauptursache wird auf der Microsoft Support-Seite beschrieben.

Die Response.End-Methode beendet die Seitenausführung und verschiebt die Ausführung auf das Application_EndRequest-Ereignis in der Ereignispipeline der Anwendung. Die Codezeile, die auf Response.End folgt, wird nicht ausgeführt.

Die bereitgestellte Lösung lautet:

Rufen Sie für Response.End die Methode HttpContext.Current.ApplicationInstance.CompleteRequest anstelle von Response.End auf, um die Codeausführung für das Ereignis Application_EndRequest zu umgehen

Hier ist der Link: https://support.microsoft.com/en-us/help/312629/prb-threadabortexception-occurs-if-you-use-response-end--response-redi

Anjani
quelle
0

Leeren Sie die Antwort an den Client, bevor Sie auf response.end () antworten.

Weitere Informationen zur Response.Flush-Methode

Verwenden Sie also vorher den unten genannten Code response.End();

response.Flush();  
thejustv
quelle
0

Ich habe alle oben genannten Änderungen verwendet, aber ich habe immer noch das gleiche Problem in meiner Webanwendung erhalten.

Dann kontaktierte ich mein Hosting-Angebot und bat sie zu prüfen, ob Software oder Antivirenprogramme unsere Dateien für die Übertragung über HTTP blockieren. oder ISP / Netzwerk lässt keine Dateiübertragung zu.

Sie haben die Servereinstellungen überprüft und die "Data Center Shared Firewall" für meinen Server umgangen. Jetzt kann unsere Anwendung die Datei herunterladen.

Hoffe, diese Antwort wird jemandem helfen. Das hat bei mir funktioniert

Sushil Jadhav
quelle
Es könnte zwar funktionieren, klingt aber nicht nach einer soliden Lösung. Wollen Sie damit sagen, dass die Firewall vollständig deaktiviert ist? Das wäre ein großes "Nein". Oder ist es für Ihre Anwendung angepasst? Es ist auch seltsam, eine ThreadAbortException für etwas zu sehen, das die Firewall des Rechenzentrums blockiert. Mit anderen Worten, keine Antwort auf die Frage?
Michael
0

Ich habe den Grund gefunden. Wenn Sie Update-Panels entfernen, funktioniert es einwandfrei!

WSJayaruwan Sumathirathne
quelle
4
sollte im Kommentar sein
TarangP
0

Ich empfehle diese Lösung:

  1. Nicht benutzen response.End();

  2. Deklarieren Sie diese globale Variable: bool isFileDownLoad;

  3. Gleich nach deinem (response.Write(sw.ToString());) set ==> isFileDownLoad = true;

  4. Überschreiben Sie Ihren Render wie folgt:

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

Ich fand, dass das Folgende besser funktionierte ...

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

Für mich hat es geholfen, eine Schaltfläche zu registrieren, die Code hinter Code als Postback-Steuerelement aufruft.

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