Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is it thread safe to register for a c# event?

specifically, is the "+=" operation atomic? does it make a difference if i'm using the 'event' keyword, or just a plain old delegate?

with most types, its a read, then the "+" operator, and then a write. so, it's not atomic. i'd like to know if there's a special case for delegates/events.

is this kind of code necessary, or redundant:

Action handler;
object lockObj;
public event Action Handler {
    add { lock(lockObj) { handler += value; } }
    remove { lock(lockObj) { handler -= value; } }
}
like image 908
notallama Avatar asked Apr 02 '14 23:04

notallama


People also ask

How do I make my property thread-safe?

If it's critical that you read the correct values each time, then you'll need to make the property thread-safe. In this article, I'll show two ways to make this property thread-safe: by using a lock and by using the Interlocked class.

What does thread-safe mean c?

Thread safety is a computer programming concept applicable to multi-threaded code. Thread-safe code only manipulates shared data structures in a manner that ensures that all threads behave properly and fulfill their design specifications without unintended interaction.

What does it mean if a function is thread-safe?

A threadsafe function protects shared resources from concurrent access by locks. Thread safety concerns only the implementation of a function and does not affect its external interface.

Is constructor thread-safe C#?

If the constructor is only accessing members of that class, and not any external static classes or methods, then yes - it is thread safe.


2 Answers

Yes, the += and -= operators on auto implemented events are atomic (if a library used a custom event handler it could very easily not be atomic). From the MSDN Magazine article .NET Matters: Event Accessors

When the C# compiler generates code for MyClass, the output Microsoft® Intermediate Language (MSIL) is identical in behavior to what would have been produced using code like that in Figure 1.

Figure 1 Expanded Event Implementation

class MyClass
{
    private EventHandler _myEvent;

    public event EventHandler MyEvent
    {
        [MethodImpl(MethodImplOptions.Synchronized)]
        add 
        { 
            _myEvent = (EventHandler)Delegate.Combine(_myEvent, value);
        }
        [MethodImpl(MethodImplOptions.Synchronized)]
        remove 
        { 
            _myEvent = (EventHandler)Delegate.Remove(_myEvent, value); 
        }
    }
    ...
}

[...]

Another use for explicit event implementation is to provide a custom synchronization mechanism (or to remove one). You'll notice in Figure 1 that both the add and remove accessors are adorned with a MethodImplAttribute that specifies that the accessors should be synchronized. For instance events, this attribute is equivalent to wrapping the contents of each accessor with a lock on the current instance:

add { lock(this) _myEvent += value; } 
remove { lock(this) _myEvent -= value; }
like image 76
Scott Chamberlain Avatar answered Oct 05 '22 23:10

Scott Chamberlain


As noted here, the add handler is auto-implemented in a thread-safe way that will perform better than a lock.

What you need to be more careful of, when it comes to thread-safety on events, is how you invoke them. See Eric Lippert's post on this here.

The standard pattern for firing this event is:

Action temp = Foo;
if (temp != null)
      temp();
like image 43
StriplingWarrior Avatar answered Oct 05 '22 21:10

StriplingWarrior