2010-04-12 27 views
7

Çok fazla Windows GUI programlama yapmıyorum, bu yüzden bu, WinForms'u daha fazla tanıyan insanlarla ilgili genel bilgiler olabilir. Ne yazık ki, sorunu açıklamak için herhangi bir kaynak bulamadık, hata ayıklama sırasında bugün karşılaştım.Control.EndInvoke, istisna için çağrı yığınını sıfırlar

EndInvoke öğesini bir async temsilcisine çağırırsak. Yeniden atılan yöntemin yürütülmesi sırasında atılan istisnaları alırız. Çağrı yığını, istisnanın orijinal kaynağını yansıtacaktır. Ancak, bir Windows.Forms.Control üzerinde benzer bir şey yaparsak, Control.EndInvoke uygulaması çağrı yığınını sıfırlar. Bu basit bir testle veya Reflektör'de kodlara bakarak gözlemlenebilir. EndInvoke alakalı kod alıntısı burada:

if (entry.exception != null) 
{ 
    throw entry.exception; 
} 

anlıyorum Kontrol ve zaman uyumsuz delegeler üzerinde EndInvoke farklıdır başlarlar/ama Control.EndInvoke benzer davranışlar beklerdik.

Herhangi bir neden var mı? Denetim, async delegeleri orijinal çağrı yığınını korumak için ne yaparsa yapmaz?

cevap

1

Asıl nedenini bilmiyorum ama async delegelerinin RPC'ye benzediğini tahmin edebilirim; kontrol delegeleri ise Win32 Message gönderimine dayanabilir. Farklı teknolojiler bu nedenle bu özelliğin etkisi aynı olmayabilir. Async delege, geliştirici, farklı süreç veya bilgisayarlar arasında istisna çağrı yığınını aktarmak için kod yazacak olan tüm yeniden kodlama kodlarından yararlanırken, kontrol delegeleri de aynı işlem içerisinde RPC'yi PostMessage ile simüle edecektir. Farklı takım, farklı kod.

1

Not: Control.EndInvoke, Framework'teki birkaç Yönetilen EndInvokes'dan biridir (böylece Reflektörde kodu görebilirsiniz). Muhtemelen, orijinal desteyle yerinde duran, yönetilmeyen bir yardımcısına sahip olmalılar.

Aslında, sadeceEndInvoke yönetilen olduğunu düşünüyorum, ama bir IAsyncResult parametreyle diğer yönetilen End* rutinleri vardır. Hepsini kontrol etmedim, ancak gözden geçirmiş olduğum her şey istisnayı fırlatır ya da Stephen Cleary'nin yönlendirme çözümünü, .NET 4'ün bazı yönetilen ve yönetilmeyen shenaniganları olan GetWaiter.GetResult'u kullanmak için kullanır. yığın istisnalar için geri yüklendi.

1

ben Kontrol bu (muhtemelen sadece bir gözetim) yapmaz neden emin değilim ama UI forma Görev programlayarak .NET 4.0'da etrafında çalışabilirsiniz:

private BackgroundWorker bgw; 
    private TaskFactory uiTaskFactory; 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     this.uiTaskFactory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext()); 
     this.bgw = new BackgroundWorker(); 
     this.bgw.DoWork += bgw_DoWork; 
     this.bgw.RunWorkerAsync(); 
    } 

    void bgw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     var task = this.uiTaskFactory.StartNew(this.OuterTaskFunction); 
     try 
     { 
      task.Wait(); 
     } 
     catch (Exception ex) 
     { 
      // Note: Full stack trace preserved 
      MessageBox.Show(ex.InnerException.ToString()); 
     } 
    } 

    void OuterTaskFunction() 
    { 
     this.InnerTaskFunction(); 
    } 

    void InnerTaskFunction() 
    { 
     throw new InvalidOperationException("Blah."); 
    } 
-3

ben mesajınızın% 100'ünü okumadı bu yüzden yardımcı olur mu, yoksa sadece açık şeyler söylüyorum, ama bir istisna yakalandığında ve

"iAmAnCaughtExceptionInstance; Çağrı yığını kaydedilmez

, sadece

"atmak;" yazmalı

ve sonra çağrı yığını kaydedilir

+1

ben biliyorum ama hayata değilim çünkü çok fazla yararlı olduğu Windows.Forms.Control. –