How do I fire an event safely

2020-07-25 01:21发布

When there are no subscribers to an event how do I ensure that an exception will not be thrown if the event is fired.

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

 // Event declaration
 public event _delDisplayChange  DisplayChange;

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

3条回答
▲ chillily
2楼-- · 2020-07-25 01:37

Change this:

// Event declaration      
public event _delDisplayChange  DisplayChange;

to this:

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

This will ensure your event will always have at least one subscriber.

查看更多
混吃等死
3楼-- · 2020-07-25 01:39

Here is the recommended way to do it:

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

Copying the event handlers enumeration before checking does two things:

  1. If DisplayChange handlers becomes null between the check and the firing, you don't die
  2. If the listeners modify the DisplayChange list while enumerating through it, you don't run into oddities.

Also, you are not using the standard Event protocol. Your delegate should be:

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

Where OptionsEventArgs derives from EventArgs. Going a step further, in .Net 3.5, you should never define a delegate like this. Instead, you should just define your event:

public event EventHandler<OptionsEventArgs> DisplayChanged;

I like to take it even one step further by defining this class:

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

Then, you don't need to define OptionsEventArgs:

public event EventHandler<EventArgs<string>> DisplayChanged;

Just some stuff to think about...

查看更多
Explosion°爆炸
4楼-- · 2020-07-25 01:49

As Brian said: many sources suggest making a copy of the event before checking that it is not null:

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

This helps to make your code more thread-safe because the value of displayChangeCopy will not change between the null check and the invocation.

查看更多
登录 后发表回答