Erstens: Die meisten Klassen werden nie thread-sicher sein müssen. Verwenden Sie YAGNI : Wenden Sie Thread-Safety nur an, wenn Sie wissen, dass Sie es tatsächlich benutzen (und testen) werden.
Für das Material auf Methodenebene gibt es [MethodImpl]
:
[MethodImpl(MethodImplOptions.Synchronized)]
public void SomeMethod() {/* code */}
Dies kann auch für Accessoren (Eigenschaften und Ereignisse) verwendet werden:
private int i;
public int SomeProperty
{
[MethodImpl(MethodImplOptions.Synchronized)]
get { return i; }
[MethodImpl(MethodImplOptions.Synchronized)]
set { i = value; }
}
Beachten Sie, dass feldartige Ereignisse sind standardmäßig synchronisiert, während automatisch implementierte Eigenschaften sind nicht :
public int SomeProperty {get;set;} // not synchronized
public event EventHandler SomeEvent; // synchronized
Mir persönlich gefällt die Implementierung von MethodImpl
wenn er abschließt this
o typeof(Foo)
- was gegen die bewährte Praxis verstößt. Die bevorzugte Option ist die Verwendung eigener Schlösser:
private readonly object syncLock = new object();
public void SomeMethod() {
lock(syncLock) { /* code */ }
}
Beachten Sie, dass bei feldartigen Ereignissen die Implementierung der Sperre vom Compiler abhängt; in älteren Microsoft-Compilern ist es eine lock(this)
/ lock(Type)
- aber, in neueren Compilern verwendet er Interlocked
Updates - also thread-safe ohne die unangenehmen Teile.
Dies ermöglicht eine detailliertere Nutzung und die Verwendung von Monitor.Wait
/ Monitor.Pulse
usw. zur Kommunikation zwischen Threads.
Eine verwandte Blogeintrag (später überarbeitet ).