Po pierwsze - większość klas nigdy nie musi być bezpieczna dla wątków. Używaj YAGNI : stosuj zabezpieczenie wątków tylko wtedy, gdy wiesz, że faktycznie zamierzasz go użyć (i przetestować).
Dla rzeczy na poziomie metod jest [MethodImpl]
:
[MethodImpl(MethodImplOptions.Synchronized)]
public void SomeMethod() {/* code */}
Można tego również użyć w akcesoriach (właściwościach i zdarzeniach):
private int i;
public int SomeProperty
{
[MethodImpl(MethodImplOptions.Synchronized)]
get { return i; }
[MethodImpl(MethodImplOptions.Synchronized)]
set { i = value; }
}
Pamiętaj, że zdarzenia podobne do pól są domyślnie synchronizowane, a właściwości zaimplementowane automatycznie nie są :
public int SomeProperty {get;set;} // not synchronized
public event EventHandler SomeEvent; // synchronized
Osobiście nie lubię implementacji, MethodImpl
ponieważ blokuje this
lub typeof(Foo)
- co jest sprzeczne z najlepszymi praktykami. Preferowaną opcją jest użycie własnych zamków:
private readonly object syncLock = new object();
public void SomeMethod() {
lock(syncLock) { /* code */ }
}
Należy zauważyć, że w przypadku zdarzeń podobnych do pola implementacja blokowania zależy od kompilatora; w starszych kompilatorach Microsoft jest to lock(this)
/ lock(Type)
- jednak w nowszych kompilatorach używaInterlocked
aktualizacji - więc jest bezpieczne dla wątków bez nieprzyjemnych części.
Pozwala to na bardziej szczegółowe użycie i umożliwia użycie Monitor.Wait
/ Monitor.Pulse
etc do komunikacji między wątkami.
Powiązany wpis na blogu (później ponownie odwiedzony ).