2016-02-29 21 views
2

我有一個運行系統托盤應用程序的C#程序 - 在後臺傳輸/移動/創建/編輯文件。是否有可能有一個C#類中的多個定時器的異常處理程序?

有很多異常處理和循環處理,以防止程序崩潰/如果用戶手動刪除程序正在使用的文件卡住。

不幸的是,程序運行的計算機之一是程序崩潰。計算機很難得到,並且無法加載調試軟件(這是一個外部嵌入式PC,無法訪問網絡)。

我試圖找到崩潰的原因(如未處理的exeption),但沒有發現任何東西,因爲它是在遠程位置沒有訪問到PC。

我希望找到一種方法來使用AppDomain/UnhandledExceptionEventHandler來捕獲所有未處理的異常並將它們記錄下來進行診斷。 但是,我有(故意)在類「DoSomething.class」中的辦公室中創建的異常正在崩潰WinForm應用程序,而不是記錄異常錯誤。

我的代碼是:

//Current domain for the unhandled exception handling 
    AppDomain currentDomain; 

    [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlAppDomain)] 
    public MainForm() 
    { 
     InitializeComponent(); 

     currentDomain = AppDomain.CurrentDomain; 
     currentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionHandler); 


     CreateTimer.Interval = Settings.Default.CreateTimer; 
     CreateTimer.Start(); 
     RunCopyProtocol(); 

     ChangeFilesTimer.Interval = 10000; 
     ChangeFilesTimer.Start(); 
     RunChangeFiles(); 

     throw new Exception("ABC"); 

    } 

    public void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args) 
    { 
     try 
     { 
      Exception ex = (Exception)args.ExceptionObject; 
      SetLabel(ex); 
     } 
     finally { } 
    } 

    private string SetLabel(Exception ex) 
    { 
     String str; 

     str = ex.Message; 
     Label1.Text = str; 

     return str; 
    } 

    private void ChangeFilesTimer_Tick(object sender, EventArgs e) 
    { 
     RunChangeFiles(); 
     throw new Exception("2"); 
    } 

爲什麼不拋出新的異常調用未處理的異常錯誤? 如何使用AppDomain獲取未處理的異常處理程序來處理RunChangeFiles中的此異常/異常?

代碼上的AppDomain是基於的MSDN examples

+1

您可能對AppDomain有些誤解。UnhandledException將允許你這樣做。它不會阻止應用程序在發生未處理的異常時結束。它只是一個通知,允許您在過程結束之前清理或記錄日誌。 –

回答

2

如果你的計時器是System.Timers.Timer的原因是通過MSDN here記載:

定時器組件捕獲並抑制由事件處理程序引發的所有異常已逝的事件。

在這個類似的問題請看: How do I get the Exception that happens in Timer Elapsed event?

你必須趕上在經過處理拋出的異常,並重新拋出他們在一個線程池線程。

使用你的代碼上面,延長從引用問題的答案:

private void ChangeFilesTimer_Tick(object sender, EventArgs e) 
{ 
    try 
    { 
     RunChangeFiles(); 
    } 
    catch (Exception ex) 
    { 
     ThreadPool.QueueUserWorkItem(
      _ => { throw new Exception("Exception on timer thread.", ex); }); 
    } 
} 

如果你的計時器是System.Windows.Forms.Timer那麼你將需要掛接到Application.ThreadException事件來處理未處理的異常。

在致電Application.Run()之前訂閱此事件。


您也可以重新拋出異常之前處理Exception的日誌記錄在本地異常處理塊。

try 
{ 
    /// ... 
} 
catch (Exception ex) 
{ 
    if (ex is ArgumentException) 
    { 
     /// handle known or specific exceptions here 
    } 
    else 
    { 
     /// log then rethrow unhandled exceptions here 
     logExceptions(ex); 
     throw; 
    } 
} 
+0

如果我把「拋出新的異常(」TEST「);」在MainForm()內部。它仍然拋出異常而不被處理程序捕獲。計時器是否簡單地通過運行來抑制其他事件? ()不僅在經過時? – Luke

+0

public MainForm() { InitializeComponent(); currentDomain = AppDomain.CurrentDomain; currentDomain.UnhandledException + = new UnhandledExceptionEventHandler(UnhandledExceptionHandler); CreateTimer.Interval = Settings.Default.CreateTimer; CreateTimer.Start(); RunCopyProtocol(); ChangeFilesTimer.Interval = 10000; ChangeFilesTimer.Start(); RunChangeFiles(); 拋出新異常(「123」) } 這是代碼。在處理程序訂閱之後在MainForm()的末尾拋出新異常 – Luke

+0

您正在將UI測試異常拋出到UI線程上。爲了處理這個問題,你需要掛鉤到Application.ThreadException事件中。看看這裏:http://stackoverflow.com/a/5762806/4267590和MSDN [這裏](https://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception%28v = vs.110%29.aspx) – khargoosh

相關問題