2011-06-29 11 views
8

.Net framework 4.0 kullanarak eklentileri izole etmek için uygulama etki alanlarını kullanan küçük bir eklenti kitaplığı yazıyorum. Bu yüzden her eklentide giden kod benim kontrolümün dışında. Eklentilerin birinde işlenmemiş bir istisna kaldırıldığında, sonuçların karışık bir torbaya benzediğini gözlemledim. Onlar aşağıdaki gibidir.Çocuk Uygulama Alanlarındaki İşlenmeyen Kural Dışı Durumları, ana işlemi çökmesine engel olabilir mi?

İşlenmeyen özel durum eklentinin ana iş parçacığına atıldığında, eklentinin yürütme yöntemini çağıran ana takılabilir uygulama, onu temiz bir şekilde yakalayabilir ve işleyebilir. Orada sorun yok. Ancak,

  1. eklentisi yöntemini yürütün eklentisiyle merkezli uygulama ve işlenmeyen bir özel durum WinForm uygulama atılan bir WinForms için bir ileti döngüsü başlar (yani bir formda) daha sonra takılabilir uygulaması yalnızca yakalayabilirsiniz istisna, görsel stüdyo hata ayıklayıcısından içeriyorsa. Aksi takdirde (VS dışında çağrıldığında), ana takılabilir uygulama eklentilerle birlikte çöker.

  2. İşlenmeyen özel durum, eklentinin Execute yöntemi tarafından oluşturulan ayrı bir iş parçacığına atılırsa, takılabilir uygulamanın özel durumu yakalama şansı yoktur ve çakılır.

Ben aşağıdaki bağlantıdan bu davranışı taklit etmek için basit VS 2010 proje oluşturduk. http://www.mediafire.com/file/1af3q7tzl68cx1p/PluginExceptionTest.zip

İçinde takılabilir uygulamasında ana yöntem Bu eklenti projesi için kodudur bu

namespace PluginExceptionTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("Press enter to load plugin"); 
      Console.ReadLine(); 

      Assembly entryAsm = Assembly.GetEntryAssembly(); 
      string assemblyFileName = Path.Combine(Path.GetDirectoryName(entryAsm.Location), "EvilPlugin.exe"); 


      AppDomainSetup domainSetup = new AppDomainSetup(); 
      AppDomain domain = AppDomain.CreateDomain("PluginDomain", null, domainSetup); 
      PluginBase plugin = (PluginBase)domain.CreateInstanceFromAndUnwrap(assemblyFileName, "EvilPlugin.Plugin"); 

      Console.WriteLine("Plugin Loaded."); 

      //SCENARIO 1: WinForms based plugin 
      Console.WriteLine("Press Enter to execute winforms plugin. (Remember to click on the button in the form to raise exception)"); 
      Console.ReadLine(); 

      try 
      { 
       plugin.ExecuteWinApp(); 
      } 
      catch (Exception) 
      { 
       //The exception is caught and this gets executed only when running in visual studio debugger. Else application exits. Why? 
       Console.WriteLine("WinForms plugin exception caught. However same does not happen when run out of visual studio debugger. WHY?"); 
      } 

      //SCENARIO 2: WinForms based plugin 
      Console.WriteLine("Press Enter to execute threading plugin, wait for 3 seconds and the app will exit. How to prevent app from exiting due to this?"); 
      Console.ReadLine(); 
      try 
      { 
       plugin.ExecuteThread(); 
      } 
      catch (Exception) 
      { 
       //This never gets executed as the exception is never caught. Application exits. Why? 
       Console.WriteLine("WinForms plugin exception caught"); 
      } 

      Console.ReadLine(); 
     } 
    } 
} 

benziyor. Yukarıdaki takılabilir uygulama projesinde PluginBase sınıfından miras alınır.

namespace EvilPlugin 
{ 
    public class Plugin:PluginBase 
    { 
     public Plugin():base() 
     { 

     } 

     public override void ExecuteWinApp() 
     {    
      Application.Run(new Form1());    
     } 

     public override void ExecuteThread() 
     { 
      Thread t = new Thread(new ThreadStart(RaiseEx));   
      t.Start(); 
     } 

     private void RaiseEx() 
     { 
      Thread.Sleep(3000); 
      throw new Exception("Another Evil Exception in a seperate thread"); 
     } 
    } 
} 

Son olarak, bu eklenti nedeniyle iki senaryo (1 ve 2), yukarıda sözü edilen çıkan ana işlemini önleyebilir nasıl

namespace EvilPlugin 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void btnException_Click(object sender, EventArgs e) 
     { 
      throw new Exception("Evil Exception"); 
     } 
    } 
} 

Form kodudur?

Şimdiden teşekkürler.

cevap

1

WinForms kural dışı durumunun yönetimi için. Sen PluginBase sınıfında böyle ThreadExceptions için "tuzak" set olabilir:

public abstract class PluginBase:MarshalByRefObject 
{ 
    protected PluginBase() 
    { 
     System.Windows.Forms.Application.ThreadException += 
      (o, args) => 
      { 
       throw new Exception("UntrappedThread Exception:" + args.Exception); 
      }; 

    } 

    public abstract void ExecuteWinApp(); 
    public abstract void ExecuteThread(); 
} 

varsayılan olarak olarak, "İstisna Penceresi" size gösterecektir. Ama eğer sağlanmışsa bu işleyiciye ulaşacaktır.

Diğer iş parçacıklarından yakalama istisnasına gelince. Hiçbir yolu yoktur. Yapabileceğiniz en iyi şey, özel durumun atılmasıyla ilgili bir bildirimde bulunmaktır.

AppDomain domain = AppDomain.CreateDomain("PluginDomain", null, domainSetup); 
    domain.UnhandledException += 
     (o, eventArgs) => 
      { 
       Console.WriteLine("Exception was caught from other AppDomain: " + eventArgs.ExceptionObject); 
       Console.WriteLine("CLR is terminating?: " + eventArgs.IsTerminating); 
      }; 
+0

Yani bir AppDomain yaklaşımı bir eklenti bunun ortaya çıkardığı iş parçacığı içinde bir duruma neden sırf çökmesine benim ana app istemem gibi eklentileri kütüphaneye gitmek için yol değildir görünüyor. Sanırım benim için bir süreç içinde paketlemenin eski yoluna dönüyorum. Msdn, AppDomains'in derleme gruplarının bir yolunu sağladığını söylediğinde,% 100 doğru değildir. – Harindaka

+1

Yanıt için teşekkürler DiVan – Harindaka

+1

AppDomain veriyi yürütür, yürütmeyi değil. – DiVan

İlgili konular