2010-10-28 35 views
2

股票數據下載類有一個BarList,它可以添加新條或更新,並在最後一個條實時更改時替換最後一個條。每當此下載類向BarList類添加新條或者更改其最後一個條時,它也會調用其NotifyOnBarsAdded或NotifyOnBarChanges。我試圖獲取通知方法來引發事件,以便處理這些事件的Canvas類可以根據調用哪種通知方法來重繪最後一欄或整個圖表。問題是,當NotifyOnBarsAdded類被調用時,我得到一個NullReferenceException作爲嘗試引發事件。我正在舉辦這樣的活動:NotifyBarAdded(this, EventArgs.Empty)。這是不正確的?下面的代碼:你如何在C#中舉辦活動?

public class BarList : List<Bar> 
{ 
    private int historyHandle; 
    public event EventHandler NotifyBarChanged; 
    public event EventHandler NotifyBarAdded; 

    public BarList(int historyHandle) 
    { 
     this.historyHandle = historyHandle; 
    } 

    public BarList() 
    { 
     // TODO: Complete member initialization 
    } 

    public void NotifyOnBarChange() 
    { 
     NotifyBarChanged(this,EventArgs.Empty); 
    } 

    public void NotifyOnBarsAdded() 
    { 
     NotifyBarAdded(this, EventArgs.Empty); 
    } 

    public long handle { get; set; } 


} 
+0

要格式化代碼塊,最好用四個空格開始每行(或者您可以在編輯器中用1和0按下按鈕)。對於內聯代碼,您可以使用反引號('\'')。 – 2010-10-28 04:43:52

回答

5

你所做的是正確的,除非你必須考慮到可能沒有附加事件處理程序,這會給你一個NullReferenceException。你必須在調用之前插入一個空警戒,或者像這樣用一個空委託來初始化事件。

檢查空:

var local = NotifyBarAdded; 
if(local != null) local(this, EventArgs.Empty); 

與空代表初始化將讓你保持你已經擁有(即無需檢查null)的調用。

public event EventHandler NotifyBarAdded = delegate {}; 
+0

你也可以用'local'來調用處理程序,這實際上可以消除競態條件。 – 2010-10-28 05:02:30

+0

@本:當然。對我來說太早了。感謝您指出了這一點。 – 2010-10-28 05:15:43

2

你總是需要檢查,看看是否有人實際上已經掛在事件

public void NotifyOnBarChange() 
    { 
     if (NotifyBarChanged != null) 
       NotifyBarChanged(this,EventArgs.Empty); 
    } 

他們將你的對象,並調用是這樣的:

yourObject.NotifyBarChanged += ...their event handler ...; 
+1

請注意,此方法不是線程安全的。如果你的事件可以從多個線程訪問,你應該使用Brian的方法(http://stackoverflow.com/questions/4039790/how-do-you-raise-an-event-in-c/4039815#4039815)。 – Gabe 2010-10-28 04:45:17

+0

不幸的是,Brian的方法不是線程安全的,儘管它看起來像那裏的意圖。 – 2010-10-28 05:03:13

+0

......現在Brian解決了比賽的問題。 – 2010-10-28 05:39:48