2010-05-07 36 views
5

Tôi đang tạo sự kiện tùy chỉnh cho C# và đôi khi nó không hoạt động.Câu hỏi về sự kiện tùy chỉnh

Đây là cách tôi làm cho sự kiện này xảy ra:

private bool isDoorOpen; 
    public bool IsDoorOpen { 
     get { return isDoorOpen;} 
     private set { isDoorOpen = value; DoorsChangeState(this, null);} 
    } 

Và đây là những tuyên bố sự kiện:

//events   
    public delegate void ChangedEventHandler(Elevator sender, EventArgs e); 
    public event ChangedEventHandler PositionChanged; 
    public event ChangedEventHandler DirectionChanged; 
    public event ChangedEventHandler BreaksChangeState; 
    public event ChangedEventHandler DoorsChangeState; 

này hoạt động càng lâu càng có những phương pháp gắn liền với các sự kiện, nhưng nếu không có, nó ném một ngoại lệ ref null. Tôi đang làm gì sai?

Trả lời

10

Cách khuyến khích để gọi một sự kiện là

var handler = this.DoorsChangeState; 
if (handler != null) 
    handler(this, null); 

Lý do để sao chép xử lý tại địa phương là trong trường hợp những thay đổi xử lý sự kiện trên thread khác trong khi bạn đang kiểm tra cho null.

EDIT: Tìm thấy bài viết nói về điều kiện chủng tộc. http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx

+0

+1 đã không nhận ra vấn đề an toàn chủ đề ở đó và thực tế là các sự kiện là không thay đổi. Cảm ơn các liên kết. –

0

Nếu một sự kiện không được đăng ký khi nó xảy ra, NullReferenceException sẽ bị ném. Đây là hành vi đúng đắn, không phải điều bạn đã làm sai.

Bạn nên kiểm tra:

if(DoorsChangeState != null) 
{ 
    DoorsChangeState(this, null); // Only fire if subscribed to 
} 
0

Trước khi gọi một sự kiện bạn phải kiểm tra xem sự kiện này là null:

if (DoorsChangeState != null) 
    DoorsChangeState(this, null); 

Khi DoorsChangeState là null đó có nghĩa là không có người nghe về sự kiện đó.

0

Bạn cần kiểm tra xem sự kiện đã được đăng ký chưa.

Tôi sử dụng biểu mẫu chuẩn này để ném tất cả các sự kiện của tôi.

var temp = EventName; 
if(EventName!= null) 
    temp(this, null); 
4

Tôi biết câu hỏi này đã được thảo luận (và được trả lời) nhiều lần ở đây trên SO.

Cũng ở đâu đó ở đây tôi đã nhận các phương pháp mở rộng sau đây để làm mô hình này dễ dàng hơn để sử dụng:

public static class EventHandlerExtensions 
{ 
    public static void FireEvent<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs 
    { 
     var temp = handler; 
     if (temp != null) 
     { 
      temp(sender, args); 
     } 
    } 

    public static void FireEvent(this EventHandler handler, object sender) 
    { 
     var temp = handler; 
     if (temp != null) 
     { 
      temp(sender, EventArgs.Empty); 
     } 
    } 
} 

Vì vậy, trong mã của bạn, bạn có thể nói:

public bool IsDoorOpen 
{ 
    get { return isDoorOpen;} 
    private set 
    { 
     isDoorOpen = value; 
     DoorsChangeState.FireEvent(this); 
    } 
} 
+0

+1 Điều đó tạo ra một cú pháp rất đẹp! – MPritchard