Primo: la maggior parte delle classi non dovrà mai essere thread-safe. Usa YAGNI : applica la sicurezza dei thread solo quando sai che lo userai (e testalo).
Per le cose a livello di metodo, c'è [MethodImpl]
:
[MethodImpl(MethodImplOptions.Synchronized)]
public void SomeMethod() {/* code */}
Questo può essere utilizzato anche su accessori (proprietà ed eventi):
private int i;
public int SomeProperty
{
[MethodImpl(MethodImplOptions.Synchronized)]
get { return i; }
[MethodImpl(MethodImplOptions.Synchronized)]
set { i = value; }
}
Si noti che gli eventi simili a campi sono sincronizzati per impostazione predefinita, mentre le proprietà implementate automaticamente non sono :
public int SomeProperty {get;set;} // not synchronized
public event EventHandler SomeEvent; // synchronized
Personalmente, non mi piace l'implementazione di MethodImpl
come si blocca this
o typeof(Foo)
- che è contro le migliori pratiche. L'opzione preferita è usare i tuoi blocchi:
private readonly object syncLock = new object();
public void SomeMethod() {
lock(syncLock) { /* code */ }
}
Si noti che per eventi di tipo field, l'implementazione del blocco dipende dal compilatore; nei vecchi compilatori Microsoft è un lock(this)
/ lock(Type)
- tuttavia, nei compilatori più recenti utilizza gliInterlocked
aggiornamenti - quindi thread-safe senza le parti cattive.
Ciò consente un utilizzo più granulare e consente di utilizzare Monitor.Wait
/ Monitor.Pulse
etc per comunicare tra i thread.
Un post di blog correlato (successivamente rivisitato ).