Metoda przedłużania ceracji, taka jak ta sugerowana, nie rozwiązuje problemów związanych z warunkami wyścigu, ale raczej je ukrywa.
public static void SafeInvoke(this EventHandler handler, object sender)
{
if (handler != null) handler(sender, EventArgs.Empty);
}
Jak stwierdzono, ten kod jest eleganckim odpowiednikiem rozwiązania z tymczasową zmienną, ale ...
Problem z obojgiem polega na tym, że możliwe jest wywołanie abonenta wydarzenia PO wypisaniu się z wydarzenia . Jest to możliwe, ponieważ anulowanie subskrypcji może nastąpić po skopiowaniu wystąpienia delegata do zmiennej tymczasowej (lub przekazaniu jako parametru w powyższej metodzie), ale przed wywołaniem delegata.
Generalnie zachowanie kodu klienta jest w takim przypadku nieprzewidywalne: stan komponentu nie mógł już pozwolić na obsługę powiadomienia o zdarzeniu. Możliwe jest napisanie kodu klienta w taki sposób, aby go obsłużyć, ale spowodowałoby to niepotrzebną odpowiedzialność po stronie klienta.
Jedynym znanym sposobem zapewnienia bezpieczeństwa wątków jest użycie instrukcji lock dla nadawcy zdarzenia. Gwarantuje to, że wszystkie subskrypcje \ unsubscriptions \ invocation są serializowane.
Aby być dokładniejszym, blokada powinna być zastosowana do tego samego obiektu synchronizacji, który jest używany w metodach dostępu do zdarzenia add \ remove, czyli domyślnie „this”.