2010-09-20 27 views
31

Tôi đang làm việc với ứng dụng Windows Forms và hava một lớp người quản lý sử dụng System.Timers.Timer để kiểm tra định kỳ dữ liệu từ cơ sở dữ liệu.Làm cách nào để nhận ngoại lệ xảy ra trong sự kiện Hẹn giờ đã trôi qua?

Làm cách nào để nhận ngoại lệ xảy ra trong bộ hẹn giờ Ứng dụng xử lý sự kiện đã giao vào ứng dụng chính? Nếu tôi đang sử dụng mã dưới đây, ngoại lệ của nhận được "nuốt", và ứng dụng chính không bao giờ được nó (ngay cả khi tôi có xử lý cho ThreadException và UnHandledException).

// 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); 
     } 
    } 

Trả lời

22

Kể từ System.Timers.Timer nuốt bất kỳ ngoại lệ ném trong xử lý sự kiện, bạn sẽ cần phải sắp xếp các ngoại lệ đối với một chủ đề (có thể là thread UI). Bạn có thể thực hiện điều này thông qua Control.Invoke hoặc bằng cách lưu trữ thông tin lỗi trong biến thành viên và yêu cầu chuỗi giao diện người dùng kiểm tra thông tin lỗi này sau khi thao tác hoàn tất. Nếu không null, giao diện người dùng có thể ném.

Từ MSDN:

Trong phiên bản .NET Framework 2.0 và trước đó, các thành phần hẹn giờ bắt và ngăn chặn tất cả các trường hợp ngoại lệ ném bởi xử lý sự kiện cho sự kiện đã qua . Hành vi này chịu sự thay đổi của trong các phiên bản tương lai của .NET Framework.

Chỉ cần đăng ký .NET 4.0 và hành vi này vẫn chưa thay đổi.

+1

Ví dụ mã Xin vui lòng? – hrh

+0

Tôi nghĩ rằng tôi nhận được nó, tôi đã thông qua ngoại lệ cho một chức năng trên chủ đề chính của tôi và sau đó chức năng được sử dụng this.Invoke() trên chức năng trước khi lại ném ngoại lệ. Tôi có hiểu chính xác điều này không? – hrh

+0

Có phương pháp mới nào để phát hiện lỗi không mong muốn tại .net 4.5 không? Nó vẫn còn nuốt và không có anyway để đăng nhập lỗi mà không cần gói toàn bộ _timer_Elapsed bên trong cố gắng bắt? – MonsterMMORPG

4

Bạn có thể gán các ngoại lệ đối với một biến địa phương và kiểm tra xem một ngoại lệ đã được ném:

// 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

Nếu bạn không có quyền truy cập vào các chủ đề chính, bạn có thể ném ngoại lệ ngày khác, không chủ đề -timer:

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

Rất đẹp. Điều này bảo tồn theo dõi ngăn xếp và bơm ngoại lệ cho AppDomain.UnhandledException. Cảm ơn bạn! – Nathan

+0

Tôi có một vòng lặp vô hạn bằng cách sử dụng phương pháp này. Ngoại lệ được ném và xử lý bởi 'AppDomain.UnhandledException' luôn. Làm thế nào tôi có thể tránh điều này? – anmarti

+0

Tuyệt vời. Cảm ơn rất nhiều. –

2

tôi đoán rằng bạn muốn xử lý các ngoại lệ về hình thức chính, giải pháp này là không hoàn thành nhưng cho thấy làm thế nào để làm điều đó với một "Action"

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); 
     } 
    } 

} 
Các vấn đề liên quan