Thread-safety always needs a context - a from what.
If you mean the +=
For the +=
, that depends on how the event is implemented. If it is implemented as a field-like event, i.e.
public event SomeEventType EventReceived;
then yes: it is thread-safe. The specification requires that the accessors for field-like events are thread-safe, although the implementation can vary (for example, the MS compiler used to use lock(this)
or lock(typeof(DeclaringType))
, however it now uses Interlocked
instead).
If the event is implemented manually, i.e.
public event SomeEventType EventReceived {
add { ... }
remove { ... }
}
Then the thread-safety is defined entirely by the add
/remove
implementations.
If you mean the invoke
Then that is thread-safe since delegates are immutable, but note that it all happens on the single thread that invokes the thread. However, a common mistake is to introduce a race condition in a null
test:
if(EventReceived != null) EventReceived(this, someArgs);
The above is not thread-safe, since technically the value of EventReceived
can change after the test. To ensure this does not error, it should be:
var handler = EventReceived;
if(handler != null) handler(this, someArgs);
If you mean the handlers
Then the thread-safety is defined entirely by the individual handlers. For example, in UI applications it is the handlers that must check for, and switch to, the UI thread.