2008-12-07 11 views
13

Application.ThreadException olay işleyicisinde istisnalar atıp onları yakalarken bazı garip davranışlar görüyorum.Neden iç istisna ThreadException işleyicisine ulaşıyor ve gerçek atılan özel durum değil?

Temel olarak aşağıdaki örnekte neler oluyor, BackgroundWorker'un DoWork olay işleyicisinde bir istisnanın atılmasıdır. RunWorkerCompleted olay işleyicisi, iç istisna olarak orijinal ile yeni bir özel durum oluşturur.

İç istisna ThreadException olay işleyicisinde neden ortaya çıkıyor ve acutal istisna atılıyor? RunWorkerCompleted olay işleyicisinde iç bir istisna sağlamazsam, doğru istisna görünecektir.

using System; 
using System.Windows.Forms; 
using System.ComponentModel; 

namespace WierdExceptionApp 
{ 
    class WierdExceptionForm : Form 
    { 
     BackgroundWorker worker = new BackgroundWorker(); 

     public WierdExceptionForm() 
     { 
      worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
      worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); 
      worker.RunWorkerAsync(); 
     } 

     void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      if (e.Error != null) 
      { 
       throw new Exception("worker_RunWorkerCompleted", e.Error); 
      } 
     } 

     void worker_DoWork(object sender, DoWorkEventArgs e) 
     { 
      throw new Exception("worker_DoWork"); 
     } 

     [STAThread] 
     static void Main() 
     { 
      Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); 
      Application.Run(new WierdExceptionForm()); 
     } 

     static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) 
     { 
      MessageBox.Show(e.Exception.Message); 
     } 
    } 
} 
+0

Şaşırtıcı; Bu benim fark etmeden yıllardır beni ısırıyor. İşlediğim için yemin edebileceğim şeyler için bu sıkıntılı raporları görebiliyordum. Onlara bakmak için çok fazla zaman harcamayacak kadar azdı, ama nihayetinde önemli bir şeyle başlamıştı ve istisna durumun değiştiğini fark ettim. O NE LAN?? –

cevap

9

RunWorkerCompleted olayı, Control.Invoke() işini yapan WF tesisatı tarafından BGW iş parçacığından UI iş parçacığına dönüştürülür. Esasen, mesaj döngüsü tarafından boşaltılan delegeler ile bir kuyruk var. Bunu yapan kod, Control.InvokeMarshaledCallbacks(), çağrı yığınında görürsünüz, işlenmeyen özel durumları yakalamak için bir catch (Exception) yan tümcesi vardır. Bu madde, Exception.GetBaseException() değerini geçirerek Application.OnThreadException çağırır.

Bu, neden yalnızca iç istisnayı gördüğünüzü açıklıyor. Neden bu şekilde yapılırsa biraz belirsizdir. Gerçek istisna arka plan iş parçacığından geldiği için, aksi takdirde oldukça kafa karıştırıcı olan UI iş parçacığı kodunun yığın çerçevelerini kesmek mümkündür.

+8

Yine de WinForms'ta Microsoft'un en kesin olarak düzeltmediği bir başka * hata! – Joshua

+1

Bu ne kadar aptal! MS kesinlikle bunu asla düzeltmez, çünkü gözlerinde bir “kırılma değişikliği” olur. Herkese yine de https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=433765 adresine gidip sorunu kaydettirelim. –

0
 if (e.Error != null) 
     { 
      throw new Exception("worker_RunWorkerCompleted", new Exception("Inner", new Exception("Inner inner"))); 
     } 

Sen sonundaki "iç iç" olsun. Bu, en içteki özel duruma bakmak için Application_ThreadException yönteminin davranışı gibi görünüyor.

İlgili konular