Ответ 1
Сначала - большинство классов никогда не должны быть потокобезопасными. Используйте YAGNI: используйте только безопасность потоков, когда вы знаете, что собираетесь использовать ее (и протестируйте ее).
Для материала уровня метода существует [MethodImpl]
:
[MethodImpl(MethodImplOptions.Synchronized)]
public void SomeMethod() {/* code */}
Это также можно использовать для аксессуаров (свойств и событий):
private int i;
public int SomeProperty
{
[MethodImpl(MethodImplOptions.Synchronized)]
get { return i; }
[MethodImpl(MethodImplOptions.Synchronized)]
set { i = value; }
}
Обратите внимание, что по-умолчанию синхронизированные по-разному события синхронизируются, тогда как автоматически реализуемые свойства не являются:
public int SomeProperty {get;set;} // not synchronized
public event EventHandler SomeEvent; // synchronized
Лично мне не нравится реализация MethodImpl
, поскольку он блокирует this
или typeof(Foo)
- что противоречит лучшей практике. Предпочтительным вариантом является использование ваших собственных блокировок:
private readonly object syncLock = new object();
public void SomeMethod() {
lock(syncLock) { /* code */ }
}
Обратите внимание, что для полевых событий реализация блокировки зависит от компилятора; в старых компиляторах Microsoft это lock(this)
/lock(Type)
- однако запись в блоге (позже revisited).