Согласно документации System.MulticastDelegate :
Thread Safety
Любые открытые статические (Shared в Visual Basic) члены этого типа являются потокобезопасными. Ни один из членов экземпляра не гарантированно является потокобезопасным.
То же утверждение существует в документации для System.Delegate.
Теперь у делегатов есть неизменный API, но, как объясняет Эрик Липперт , «ошибочно полагать, что только потому, что структура данных не допускает никакого способа для , вы меняете ее содержимое, ее реализация должна быть поточно-безопасной! "
Некоторые механизмы для создания новых делегатов из существующих делегатов являются статическими методами: Delegate.Combine
и Delegate.Remove
. Похоже, что они потокобезопасны. Имея многоадресных делегатов A, B и C, я могу смело комбинировать A и B, чтобы создать D в одном потоке, а B и C создать E в другом.
Но вызов делегата не является статическим методом. Означает ли это, что технически мой код может сломаться, если я разделю делегат между потоками и вызову его в обоих, или если я вызову делегат в одном потоке, комбинируя его с другим в другом потоке? Может ли реализация, соответствующая стандартам, MulticastDelegate
привести к неопределенному поведению в таком сценарии? Гарантируется, что делегат, возвращенный Combine
или Remove
, не делит скрытое изменяемое состояние с каким-либо другим делегатом?
Обратите внимание, что я спрашиваю о том, что стандарт гарантирует , а не о текущем поведении компиляторов C # и CIL JIT. Экспериментально я могу определить, что это действительно кажется безопасным, используя каждый из .NET и Mono на доступных мне архитектурах, но я не вижу, что определяет или гарантирует это поведение.