2010-09-20 13 views
31

Windows Forms uygulamasıyla çalışıyorum ve veritabanından verileri düzenli olarak kontrol etmek için System.Timers.Timer kullanan bir yönetici sınıfını çalıştırıyorum.Zamanlayıcı Elapsed olayında gerçekleşen Özel Durum'u nasıl alabilirim?

Zamanlayıcı Elapsed eventhandler uygulamasında ana özelliğe uygulanan Özel Durum'u nasıl alabilirim? Aşağıdaki kodu kullanıyorum, istisna get "yutuldu" ve ana uygulama asla (ThreadException ve UnHandledException için işleyiciler varsa bile) alır. olay işleyicisi atılmış

// Main Form 
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); 
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); 

// Manager class 
private System.Timers.Timer _timer; 

    void _timer_Elapsed(object sender, ElapsedEventArgs e) 
    { 
     try 
     { 
      doSomeDatabaseActions(); 
     } 
     catch (Exception ex) 
     { 
      throw new ApplicationException("How do I get this error back into main thread...", ex); 
     } 
    } 

cevap

22

System.Timers.Timer yana kırlangıçlar herhangi bir istisna, başka iş parçacığı (muhtemelen UI iş parçacığı) istisna sıralamakta gerekecektir. Bunu Control.Invoke aracılığıyla veya bir üye değişkenindeki hata bilgilerini saklayarak ve UI iş parçacığına sahip olmak, işlem tamamlandıktan sonra bu hata bilgisini kontrol ederek yapabilirsiniz. null değilse, UI atlayabilir. MSDN itibaren

: .NET Framework sürüm 2.0 ve önceki yılında

, Zamanlayıcı bileşen Geçen olay için olay işleyicileri tarafından atılan tüm istisnalar yakalar ve bastırır. Bu davranış, .NET Framework'ün sonraki sürümlerinde değişikliğine tabidir.

Sadece .NET 4.0'da işaretlenmiş ve bu davranış henüz değişmemiştir.

+1

Kod Örneği Lütfen? – hrh

+0

Sanırım anladım, ana iş parçacığımdaki bir işlevin istisnasını geçtim ve bu işlevin istisnayı atmadan önce this.Invoke() işlevini kullandı. Bunu doğru anlıyor muyum? – hrh

+0

.net 4.5'de beklenmedik hataları yakalamak için herhangi bir yeni yöntem var mı? Hala yutar ve orada hiçbir _timer_Elapsed yakalama yakalama olmadan hataları günlüğe kaydetmek için orada değiliz? – MonsterMMORPG

4

yerel bir değişkene istisna atar ve bir özel durum olup olmadığını kontrol edebilirsiniz: Eğer ana iş parçacığı erişimi yoksa, başka üzerinde istisna atabilir

// Main Form 
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); 
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); 

// Manager class 
private System.Timers.Timer _timer; 

    private exception = null; 

    void _timer_Elapsed(object sender, ElapsedEventArgs e) 
    { 
     //reset the exception in case object is reused. 
     this.exception = null; 
     try 
     { 
      doSomeDatabaseActions(); 
     } 
     catch (Exception ex) 
     { 
      this.exception = ex; 
     } 
    } 

    /** 
    * Checks whether the exception object is set. 
    */ 
    public bool hasExceptionOccured(){ 
     return (this.exception != null); 
    } 

    //The main application will call this to get the exception. 
    public Exception getException(){ 
     return this.exception; 
    } 
26

, sigara -Timer iplik: ne ana formdaki istisna işlemek istediğinizi tahmin

catch (Exception exception) 
{ 
    ThreadPool.QueueUserWorkItem(
     _ => { throw new Exception("Exception on timer.", exception); }); 
} 
+0

Güzel. Bu yığın izlemeyi korur ve özel durumu AppDomain.UnhandledException olarak pompalar. Teşekkür ederim! – Nathan

+0

Bu yaklaşımı kullanarak sonsuz bir döngüye sahibim. İstisna her zaman "AppDomain.UnhandledException" tarafından atılır ve işlenir. Bundan nasıl kurtulabilirim? – anmarti

+0

Harika. Çok teşekkürler. –

2

, bu çözüm tam değildir ama

using System; 
using System.Timers; 


public class MainForm 
{ 
    public MainForm() 
    { 
     var tm = new TestManager(exception => 
     { 
      //do somthing with exception 
      //note you are still on the timer event thread 
     }); 

    } 
} 

public class TestManager 
{ 
    private readonly Action<Exception> _onException; 

    public TestManager(System.Action<System.Exception> onException) 
    { 
     _onException = onException; 

    } 


    private System.Timers.Timer _timer; 
    void _timer_Elapsed(object sender, ElapsedEventArgs e) 
    { 
     try 
     { 
      doSomeDatabaseActions(); 
     } 
     catch (Exception ex) 
     { 
      //throw new ApplicationException("How do I get this error back into main thread...", ex); 
      _onException(ex); 
     } 
    } 

} 
bir "Aksiyon" ile nasıl yapılacağını gösterir
İlgili konular