2009-07-15 18 views
5

widziałem tego rodzaju kodu kilka miejsc:C#: Inicjowanie programu obsługi zdarzeń z manekina

public event SomeEventHandler SomeEvent = (s, e) => { }; 

Czy to zalecany sposób robienia rzeczy? Co to rozwiązuje i czy ma jakieś godne uwagi efekty uboczne? Czy nadal będę musiał sprawdzać wartości null? Czy jest to dokładnie to, czego nie muszę robić? Czy wywóz śmieci nadal działa tak, jak powinien?


Na przykład:

private PropertyChangedEventHandler propertyChanged; 
private readonly object propertyChangedLock = new object(); 
public event PropertyChangedEventHandler PropertyChanged 
{ 
    add 
    { 
     lock (propertyChangedLock) 
      propertyChanged += value; 
    } 
    remove 
    { 
     lock (propertyChanged) 
      propertyChanged -= value; 
    } 
} 
protected void OnPropertyChanged(string propertyName) 
{ 
    PropertyChangedEventHandler handler; 
    lock (propertyChangedLock) 
     handler = propertyChanged; 

    if (handler != null) 
     handler(this, new PropertyChangedEventArgs(propertyName)); 
} 

Czy mogę zmienić pierwszą linię do tego:

private PropertyChangedEventHandler propertyChanged = (s, e) => { }; 

a następnie przejdź null-czek w metodzie OnPropertyChanged? A jeśli pominiemy kontrolę zerową, czy mogę pominąć blokadę? Jeśli tak, to dałoby mi to:

protected void OnPropertyChanged(string propertyName) 
{ 
    propertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
} 

Czy byłoby to bezpieczne, biorąc pod uwagę inicjalizację? Czy są jakieś efekty uboczne, które przeoczyłem?

+2

Mój artykuł na ten temat: http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx –

+0

Przyjemny artykuł! Innymi słowy, usunięcie kontroli zerowej byłoby w tym przypadku wątkowo bezpieczne. Ale subskrybenci muszą mieć inteligentne procedury obsługi, które się nie psują. Czy to rozumiem? – Svish

Odpowiedz

7

Podczas gdy nie musisz wykonywać kontroli nieważności, jeśli naprawdę chcesz spróbować zrobić wydarzenie wątku bezpieczny, trzeba jeszcze, aby sprowadzić go do zamka:

protected void OnPropertyChanged(string propertyName) 
{ 
    PropertyChangedEventHandler handler; 
    lock (propertyChangedLock) 
    { 
     handler = propertyChanged; 
    } 
    handler(this, new PropertyChangedEventArgs(propertyName)); 
} 

w przeciwnym razie nie można pobierania najnowszej wartość - jeśli obsługi zdarzeń są dodawane w innym wątku, można teoretycznie podnieść zdarzenia na zawsze, nie dzwoniąc do nowych opiekunów. W praktyce wierzę, że prawie zawsze uciekniesz bez zamka, ale w kategoriach modelu pamięci powinieneś mieć pewien rodzaj ogrodzenia.

Osobiście polecam, aby nie spróbuj, aby zdarzenia były bezpieczne dla wątków.

+0

Więc wolałbyś po prostu pominąć wszystkie wątki bezpieczne? – Svish

+0

Tak. Uzyskaj dzwoniących do subskrybowania w odpowiednim wątku. –

+0

Jak byś to zrobił? – Svish

0

Możesz to zobaczyć jako implementację NULL Object pattern.

Pomaga uczynić twój kod czytelniejszym, ponieważ nie musisz robić NULL - sprawdzanie wartości.

Zamki w logice dodawania/usuwania będą musiały pozostać, jeśli będą teraz potrzebne. Nie mają z tym nic wspólnego. Są używane w celu uniknięcia wyścigów (ale nie wiem, czy są one niezbędne w twojej sytuacji)

Powiązane problemy