Отриманий спосіб продовження, як запропонований, насправді не вирішує проблем з умовами перегонів, а навпаки, приховує їх.
public static void SafeInvoke(this EventHandler handler, object sender)
{
if (handler != null) handler(sender, EventArgs.Empty);
}
Як зазначено, цей код є елегантним еквівалентом рішення з тимчасовою змінною, але ...
Проблема обох, що цілком можливо, що субцибер події може бути названий ПІСЛЯ відмови від події . Це можливо, оскільки скасування підписки може відбутися після того, як екземпляр делегата буде скопійовано у змінну temp (або передано як параметр у наведеному вище методі), але до того, як буде викликаний делегат.
Взагалі поведінка коду клієнта в цьому випадку непередбачувана: стан компонента вже не може обробляти повідомлення про події. Можна написати клієнтський код таким чином, щоб з ним обробляти, але це покладе на клієнта непотрібну відповідальність.
Єдиний відомий спосіб забезпечити безпеку потоку - використовувати оператор блокування для відправника події. Це гарантує, що всі підписки \ відписки \ виклик серіалізовані.
Щоб бути точнішим, блокування слід застосовувати до того самого об'єкта синхронізації, що використовується в методах додавання / видалення події, який за замовчуванням є "цим".