今まで、イベントを発生させるメソッドを何も考えずに
public event EventHandler<HelloEventArgs> Hello;
protected virtual void OnHello(HelloEventArgs e)
{
if (Hello != null)
{
Hello(this, e);
}
}
と書いていたけど、どうやらこれはマズイみたい。
スレッドセーフじゃない。
if (Hello != null)
を満たして
Hello(this, e);
に来るまでの間に、別のスレッドで
// クラス外部からイベントハンドラを解除するときは -= で行う。
// ↓ができるのはクラス内部だけ。
// Hello = null;
とされたら
全てのイベントハンドラが解除されたら NullReferenceException が発生してしまう。なので
public event EventHandler<HelloEventArgs> Hello;
protected virtual void OnHello(HelloEventArgs e)
{
EventHandler<HelloEventArgs> tmp = Hello;
if (tmp != null)
{
tmp(this, e);
}
}
と書くのが望ましい。
これならと書けば、Hello がもともと null のときは if の条件を満たさないし、
別スレッドで Hello を null にされても tmp は null にならないので、
NullReferenceException は発生しない。