Вам нужно заблокировать и при получении обработчика, иначе у вас может не быть последнего значения:
protected void OnProcessingCompleted(ProcessCompletedEventArgs e)
{
EventHandler<ProcessCompletedEventArgs> handler;
lock (completedEventLock)
{
handler = ProcessCompleted;
}
if (handler != null)
handler(this, e);
}
Обратите внимание, что это не предотвращает состояние гонки, когда мы решили, что мы собираемся выполнить набор обработчиков, и затем один обработчик отписался. Он по-прежнему будет вызываться, потому что мы получили делегат многоадресной рассылки, содержащий его, в переменную handler
.
Вы ничего не можете с этим поделать, кроме как заставить самого обработчик осознавать, что он больше не должен вызываться.
Возможно, лучше просто не попытаться сделать события потокобезопасными - указать, что подписка должна только изменить поток, который вызовет событие.