如何安全地开火活动

时间:2009-12-08 18:21:27

标签: c# events .net-2.0

如果事件没有订阅者,我如何确保在事件被触发时不会抛出异常。

 // Delegate declaration
 public delegate void _delDisplayChange(object sender,string option);

 // Event declaration
 public event _delDisplayChange  DisplayChange;

 //throwing the event
 DisplayChange(this, "DISTRIBUTION");

4 个答案:

答案 0 :(得分:18)

以下是推荐的方法:

protected void RaiseDisplayChanged(string message)
{
    var handlers = DisplayChange;
    if(handlers != null)
        handlers(this, message);
}

在检查之前复制事件处理程序枚举有两件事:

  1. 如果DisplayChange处理程序在检查和触发之间变为空,则不会死亡
  2. 如果侦听器在枚举时修改DisplayChange列表,则不会遇到奇怪的现象。
  3. 此外,您没有使用标准的事件协议。你的代表应该是:

    public delegate void DisplayChangeDelegate(object sender, OptionsEventArgs args);
    

    OptionsEventArgs派生自EventArgs。更进一步,在.Net 3.5中,你永远不应该像这样定义一个委托。相反,您应该只定义您的事件:

    public event EventHandler<OptionsEventArgs> DisplayChanged;
    

    我喜欢通过定义这个类来更进一步:

    public class EventArgs<T> : EventArgs
    {
        public T Payload { get; private set }
        public EventArgs(T payload)
        {
            Payload = payload;
        }
    }
    

    然后,您不需要定义OptionsEventArgs:

    public event EventHandler<EventArgs<string>> DisplayChanged;
    

    只需考虑一些事情......

答案 1 :(得分:4)

改变这个:

// Event declaration      
public event _delDisplayChange  DisplayChange;

到此:

// Event declaration      
public event _delDisplayChange  DisplayChange = delegate{};

这将确保您的活动始终至少有一个订阅者。

答案 2 :(得分:1)

正如Brian所说:许多消息来源建议在检查事件是否为空之前制作事件的副本:

_delDisplayChange displayChangeCopy = DisplayChange;
if (displayChangeCopy != null)
    displayChangeCopy(this, "DISTRIBUTION");

这有助于使代码更加线程安全,因为displayChangeCopy的值在null检查和调用之间不会改变。

答案 3 :(得分:1)

继Jay的回答之后,这里有一个link关于使用空委托时的性能考虑因素。