You need to lock when you fetch the handler too, otherwise you may not have the latest value:
protected void OnProcessingCompleted(ProcessCompletedEventArgs e)
{
EventHandler<ProcessCompletedEventArgs> handler;
lock (completedEventLock)
{
handler = ProcessCompleted;
}
if (handler != null)
handler(this, e);
}
Note that this doesn't prevent a race condition where we've decided we're going to execute a set of handlers and then one handler unsubscribed. It will still be called, because we've fetched the multicast delegate containing it into the handler
variable.
There's not a lot you can do about this, other than making the handler itself aware that it shouldn't be called any more.
It's arguably better to just not try to make the events thread-safe - specify that the subscription should only change in the thread which will raise the event.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…