Yanıttan Nasıl Kaçınılır.End () Excel dosyası indirilirken "İş parçacığı iptal ediliyor" İstisnası


97

Veri setimi excel'e dönüştürmeye ve o excel'i indirmeye çalıştım. Bu sorun nasıl çözülür? .. Lütfen bana yardım edin ...

Ben aspx ekranımda bu metodu çağırıyorum, bu metotla aynı istisna oluştu.

Bu genel void ExportDataSet (DataSet ds) işlevini birçok aspx ekranında çağırıyorum ve ayrıca çalışma zamanında ortaya çıkan istisnalar için hata günlüğü yöntemini sürdürüyorum, bu istisnalar bir .txt dosyalarına yazılır. Böylece, aynı istisna tüm aspx ekranının txt dosyalarında günlüğe kaydedilir. Bu istisnanın, yöntem bildirilen sınıf dosyasından aspx'e atılmasını önlemek istiyorum. Sadece bu istisnayı yöntem bildirim sınıf dosyamın kendisinde ele almak istiyorum.

ASPX Dosya Yöntemi çağrısı: excel.ExportDataSet (dsExcel);

Yöntem Tanımı:

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
Kullanmayın Response.Endbkz. Stackoverflow.com/a/3917180/2864740 (ve diğer yanıtlar); yığının nasıl çözüldüğü için istisnanın "beklenilmesi gereken" olduğunu unutmayın (bu nedenle bu istisnayı yakalamayın). Yine de [diğer] istisnaları yakalamak istiyorsanız, şunu kullanın:.. catch (ThreadAbortException) { throw; /* propagate */ } catch (Exception ex) { .. }
user2864740

Yanıtlar:


198

İnternette araştırma yaptım ve Response.End()her zaman bir istisna getirdiğini gördüm .

Bunu değiştirin: HttpContext.Current.Response.End();

Bununla:

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
Bir nimettir vay. WinDbg kullanarak saatlerce hata ayıklamamı kurtardı. Benim durumumda, benim w3wp.exe sadece çok fazla ThreadAbortException varsa çöktü
Dio Phung

Teşekkürler. Bu kod parçası, asmx hizmet kurucusuna bazı yetkilendirme denetimi eklemek istiyorsanız gerçekten yararlıdır
vadim

Bu benim için çalıştı. .End () 'yi önerilen kodla değiştirdim ve şimdi istisnasız çalışıyor. Teşekkürler, şimdi çalışma kodum: Response.ContentType = "text / csv"; Response.AddHeader ("Content-Disposition", string.Format ("attachment; dosyaadı = \" {0} \ "", Path.GetFileName (dosyaYolu))); Response.TransmitFile (filePath); //Response.End (); HttpContext.Current.Response.Flush (); HttpContext.Current.Response.SuppressContent = true; HttpContext.Current.ApplicationInstance.CompleteRequest ();
Nour Lababidi

3
Hayır. Benim için çalışmıyor. Aslında cevaba bakın. Eğer Response.End()yok değil çalışmak, neden önerilen cevabı da vardır Response.End()son satırında? Bunun yerine @Binny'nin (aşağıda) cevabı yardımcı olur!
user3454439

1
Docs.microsoft.com/en-us/dotnet/api/system.web.httpresponse.end adresindeki belgelere göre Request.End yalnızca geriye dönük uyumluluk için desteklenir. Yedek olarak CompleteRequest kullanımı önerilir
Rudolf Dvoracek

11

Bu Thread was being aborted, istisnayı halletmeme yardımcı oldu.

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

yerine aşağıdaki kodu kullanırsanız, istisna HttpContext.Current.Response.End()alırsınız Server cannot append header after HTTP headers have been sent.

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

Umarım yardımcı olur


1
Benim için çalışıyor. Yukarıdakiler yoktur. Aslında işe Response.End()yaramazsa komik ama önerilen yöntem de Response.End()son satırda var mı?
user3454439

1
Çünkü istisnayı yakalayıp saklıyorsunuz.
Dan Friedman

3
Ne korkunç bir çözüm
Razor

4

Şununla aynı soru gibi görünüyor:

Bir ASP.NET System.Web.HttpResponse.End () çağrıldığında, geçerli iş parçacığı iptal edilir mi?

Yani tasarım gereğidir. Bu istisna için bir yakalama eklemeniz ve nazikçe "yok saymanız" gerekir.


Bu genel void ExportDataSet (DataSet ds) işlevini birçok aspx ekranında çağırıyorum ve ayrıca çalışma zamanında ortaya çıkan istisnalar için hata günlüğü yöntemini sürdürüyorum, bu istisnalar bir .txt dosyalarına yazılır. Böylece, aynı istisna tüm aspx ekranının txt dosyalarında günlüğe kaydedilir. Bu istisnanın, yöntem tarafından bildirilen sınıf dosyasından aspx'e atılmasını önlemek istiyorum. Sadece bu istisnayı yöntem bildirim sınıf dosyamın kendisinde ele almak istiyorum.
user3171957

Sorunuzdaki kullanıcıdan gelen yorum başına, TheadAbortException -> catch (ThreadAbortException) {}
robnick

Evet, bu istisnayı Yöntem bildirim sınıfında kendi kendine dosyala.
user3171957

4

Response.End () öğesini Try / Catch ve Using bloklarının dışına taşıyın.

İsteğin geri kalanını atlamak için bir İstisna atmanız gerekiyordu, sadece onu yakalamanıza gerek yoktu.

bool endRequest = false;

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

if (endRequest)
    Resonse.End();

neden bunu bir Nihayet bloğuna yerleştirmiyorsunuz, böylece her zaman yürütülür?
GoldBishop

bunu yapabilirsiniz, özellikle try bloğunda bir return ifadeniz varsa. Ama denerseniz / yakalarsanız / görmezden gelirseniz, o zaman nihayetine bile ihtiyacınız yoktur. önemli olan şey, ThreadAbortException'ı yakalamamanız gerektiğidir.
Steve

Doğru, TAE, başarılı bir Yanıtı döndürmek için bir PITA'dır.
GoldBishop

3

Sadece koy

Response.End();

try bloğu yerine bir nihayet bloğu içinde.

Bu benim için çalıştı !!!.

Aşağıdaki sorunlu (İstisna ile) kod yapısına sahiptim

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

   return;

 } 

 some_more_code...

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

}
catch(Exception){
}
finally{}

ve istisnayı fırlatır. Yanıttan sonra çalıştırılacak kod / iş olduğu yerde İstisnanın atıldığından şüpheleniyorum.End (); . Benim durumumda ekstra kod sadece dönüşün kendisiydi.

Yanıtı hareket ettirdiğimde.End (); Nihayet bloğuna (ve dönüşü onun yerine bıraktı - bu, try bloğundaki kodun geri kalanının atlanmasına ve final bloğuna atlanmasına neden olur (sadece içeren işlevden çıkmak değil)) İstisna gerçekleşmeyi durdurdu.

Aşağıdakiler iyi çalışıyor:

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

   return;

 } 

 some_more_code...

 Reponse.Write(...);

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

3

Response.End () yöntemi istisnası için özel bir catch bloğu kullanın

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

Veya bir dosya işleyicisi oluşturuyorsanız Response.End () öğesini kaldırın.



2

Bağlantı düğmesini UpdatePanel'den kaldırdım ve ayrıca Response.End () Başarılı !!!


1

Response.END () için hata; çünkü bir asp güncelleme paneli veya javascript kullanan herhangi bir denetim, javascript veya scriptmanager veya komut dosyası olmadan asp veya html'den yerel denetimi kullanmayı deneyin ve tekrar deneyin


1

Bu sorun değil ama bu tasarım gereğidir. Temel neden Microsoft Destek Sayfasında açıklanmıştır.

Response.End yöntemi, sayfanın yürütülmesini sonlandırır ve yürütmeyi uygulamanın olay ardışık düzenindeki Application_EndRequest olayına kaydırır. Response.End'i izleyen kod satırı çalıştırılmaz.

Sağlanan Çözüm şudur:

Response.End için, Application_EndRequest olayına kod yürütmeyi atlamak için Response.End yerine HttpContext.Current.ApplicationInstance.CompleteRequest yöntemini çağırın

İşte bağlantı: https://support.microsoft.com/en-us/help/312629/prb-threadabortexception-occurs-if-you-use-response-end--response-redi


0

yanıtı istemciye yanıt vermeden önce boşaltın. end ()

Response.Flush Yöntemi hakkında daha fazla bilgi

Bu nedenle, aşağıda belirtilen kodu daha önce kullanın response.End();

response.Flush();  

0

Yukarıdaki tüm değişiklikleri kullandım ama yine de web uygulamamda aynı sorunu alıyordum.

Ardından, barındırma sağlayıcımla iletişime geçtim ve dosyalarımızın HTTP yoluyla aktarılmasını engelleyen herhangi bir yazılım veya antivirüs olup olmadığını kontrol etmelerini istedim. veya ISS / ağ dosyanın aktarılmasına izin vermiyor.

Sunucu ayarlarını kontrol ettiler ve sunucum için "Veri Merkezi Paylaşılan Güvenlik Duvarı" nı atladılar ve şimdi uygulamamız dosyayı indirebiliyor.

Umarım bu cevap birine yardımcı olur, bu benim için çalıştı


İşe yarasa da, sağlam bir çözüm gibi görünmüyor. Güvenlik duvarının tamamen devre dışı olduğunu mu söylüyorsunuz? Bu büyük bir "hayır" olur. Yoksa uygulamanız için özelleştirilmiş mi? Ayrıca, veri merkezi güvenlik duvarının engellediği bir şeyde bir ThreadAbortException görmek garip ... Başka bir deyişle, sorunun cevabı değil mi?
Michael


0

Bu çözümü tavsiye ederim:

  1. Kullanma response.End();

  2. Bu genel değişkeni bildirin: bool isFileDownLoad;

  3. Hemen sonra (response.Write(sw.ToString());) set ==> isFileDownLoad = true;

  4. Oluşturma öğenizi şu şekilde geçersiz kılın:

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

0

Aşağıdakilerin daha iyi çalıştığını buldum ...

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

0

Benim için, geri gönderme kontrolü olarak kodun arkasındaki kodu çağıran bir düğmenin kaydedilmesine yardımcı oldu.

protected void Page_Init(object sender, EventArgs e)
{
    ScriptManager.GetCurrent(this.Page).RegisterPostBackControl(btnMyExport);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.