2010-06-17 32 views
3

爲什麼'公共事件EventHandler cccc'爲空?爲什麼'公共事件EventHandler cccc'爲空?

我有一個類,是

public class Builder 
{ 
    public event EventHandler StartedWorking; 

    public Builder() 
    { 
     // Constructor does some stuff 
    } 

    public void Start() 
    { 
     StartedWorking(this, eventargobject); //StartedWorking is null -- 
    } 
} 

這看起來簡單,我做的事情所有的時間?我是否錯過了某些明顯的東西,或者是否有可能導致這種情況的東西?

編輯:

這是否意味着,如果我火是不是在客戶端類我要檢查它不是空訂閱的事件嗎?

EDIT 2:

我想我從來沒有說從來沒有不訂閱,因此從來就遇到了這個事件 - 你學到一些東西每一天 新對不起看似愚蠢的問題....

+0

Matt:關於您的編輯 - 我添加了「正確」的方式來提高事件給我回答你。你應該總是先檢查null。 – 2010-06-17 18:38:38

回答

11

事件處理程序將爲空,除非有人訂閱了該事件。一旦委託人訂閱了該事件,它將不再爲空。

這就是爲什麼它總是建議使用以下形式的籌款活動:

public void Start() 
{ 
    var handler = this.StartedWorking; 
    if (handler != null) 
    { 
     handler(this, eventArgObject); 
    } 
} 

這保護您從零異常,如果一直沒有用戶。

+4

如果事件在空檢查和調用本身之間取消訂閱,則分配變量還會阻止您處理爭用條件。 – 2010-06-17 18:53:35

0

如果你還沒有掛接任何事件訂閱者到你的StartedWorking事件,那麼它將爲空。這就是.NET事件的工作原理。

This article除其他外,表明您應該在調用事件之前檢查null。 This other question and answer演示瞭如何以避免空檢查的方式創建事件(基本上通過總是添加空處理程序)。

+0

第一篇文章(來自.NET 1.1)演示瞭如何做到這一點,但在多線程情況下它不適用。我推薦我的方法。第二篇文章有效,但可能很脆弱(可能會刪除該處理程序,這將再次導致異常),並且每次引發事件(委託調用)時都會增加開銷。 – 2010-06-17 18:46:12

0

您是否需要分配函數?

StartedWorking += new EventHandler(afunction); 

void afunction(object sender, EventArgs e) 
{ 
    DoSomething(); 
} 
2

正如其他人已經說過,因爲沒有訂閱者,它是空的。

要回答您的編輯:是的,您應該始終在觸發它之前檢查一個空的事件。但是,如果您只是做一個普通的if(StartedWorking != null){...},則可能會導致競爭狀況,因爲用戶可能會在空檢查之後但觸發事件之前取消訂閱。正因爲如此,你應該檢查事件時,空總是使用這種模式:

protected void OnStartedWorking() 
{ 
    EventHandler localEvent = StartedWorking 
    if(localEvent != null) 
    { 
     localEvent(this, EventArgs.Empty); 
    } 
} 

這通過採取事件的副本第一所以訂閱列表是固定在複印點防止競爭條件。

有更多infomration有關MSDN上發佈事件:How to Publish Events that Conform to .NET Framework Guidelines

(這工作,因爲英寸網絡MultiCastDelegate類不可改變,所以任何嘗試改變事件的訂戶列表將不會影響您所做的副本)

相關問題