From the MSDN documentation for EventHandler Delegate:
In contrast to the C# and Visual Basic examples, the Visual C++ example code does not require you to create a thread-safe temporary variable. Visual C++ version automatically provides thread-safe access, enabling you to raise the event directly.
Why can C# not automatically provide thread-safe access to events, where C++/CLI can?
Can-C's ingredients help to soothe and rejuvenate tired eyes, help with macular degeneration, cataracts, and other age-related eye disorders. Can-C eye drops for cataracts contain lubricants, an antioxidant and an anti-glycating agent, N-Acetyl-Carnosine (NAC).
The minimum time to see results from Can-C eye drops, which is generally twice per day, is 6 months.
Can-C Ingredients. Glycerin, Carboxymethylcellulose, Benzyl Alcohol, N-Acetyl Carnosine, Potassium Bicarbonate, Boric Acid. (These ingredients are not listed by weight).
Do not use this medication for longer than 3 to 4 days at a time.
This post is quite relevant for background info. An event has three accessors: add, remove and raise. Respectively to add an event handler, remove it and to raise the event. The compiler auto-generates one when you don't write an accessor explicitly.
The C++/CLI compiler auto-generates the raise accessor if you don't write one. It uses the pattern you see in C# code with the helper variable that avoids the null reference exception. Just as you see it in the linked post. For some mysterious reason the C# language doesn't do this. It doesn't even let you define your own accessor, you have to raise the event yourself. Forcing you to write code with the helper variable.
I have no clue why the C# team made this decision. As a rule, the team strongly favors avoiding auto-generated code that slows down execution. The C++ principle of 'you don't pay for what you don't use'. There are certainly many cases where the thread-safety is unnecessary, any events in GUI code for example. This is a heck of an edge-case though, given the low cost and the fact that GUI code contains the pattern anyway. Low-level locking in C++ libraries is however common.
While not exactly a duplicate, I believe the answers in this question will help explain why they aren't thread safe in terms of implementation. Specifically these two answers.
Marc Gravell's answer:
IMO, the other answers miss one key detail - that delegates (and therefore events) are immutable. The significance of this is that subscribing or unsubscribing an event handler doesn't simply append/remove to a list - rather, it replaces the list with a new one with an extra (or one less) item on it.
Since references are atomic, this means that at the point you do:
var handler = SomeEvent;
you now have a rigid instance that cannot change, even if in the next picosecond another thread unsubscribes (causing the actual event field to become null).
So you test for null and invoke it, and all is well. Note of course that there is still the confusing scenario of the event being raised on an object that thinks it unsubscribed a picosecond ago!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With