Assumptions on event raising - c#

Imagine the following class:
class A
{
public event EventHandler AnyEvent;
}
You create an instance of class A, and attach some event handlers. Now if AnyEvent gets raised, I would not assume, that the event handlers are performed on another thread, than the thread I created the object. This would be of prime importance, if you created the object on a GUI thread, and the event handler performs operations on GUI elements. This would force me to use appropriate invocation patterns.
It really becomes evil, if you use interfaces defining events:
interface B
{
event EventHandler SomeEvent;
}
Now one implementation could raise the event from the original thread, the next from a second thread. This can cause your application to successfully work with the one, and fail with the other implementation.
I think coding should always be transparent - this is not! And if I don't create another thread, I do not assume, that my methods are performed from any other than my home thread.
Are there any aspects I did not consider? Any that would invalidate my assumption?

There is no magic with events. Events are handled on the thread that raises them. It has nothing to do with the thread that creates the object.

Threading is the responsibility the consumer of the class, not the writer of the class, so your assumption is incorrect.
One should assume a class is not thread-safe unless it is documented to be thread-safe. Even most built-in .NET classes are not thread safe unless they say they are.
It is up to the consumer of the class to be aware of threading.

Calling events is just calling some method (or collection of methods) using a mechanism such as function pointers.
Events are completely oblivious to the thread that attached them, and don't have any other information that could lead to properly Invoking the methods on the right thread.
Maybe you are drawing your assumptions from COM days?

Handler callbacks for events are on the same thread that raised the event.

Related

How to prevent an event handler being called before a constructor's finished?

If I hook an event in a constructor, is there any possibility that the handler might be invoked by another thread before it's finished with the constructor?
e.g.:
private List<string> changes;
public MyClass(INotifyPropertyChanged observable) {
observable.PropertyChanged += this.Handler;
// Another thread changes a property at this point
this.changes = new List<string>();
}
private void Handler(object sender, PropertyChangedEventArgs e) {
this.changes.Add(e.PropertyName); // Breaks, because the list's not there yet
}
(Yes, I know it's trivial to avoid a problem in this example, I've got some more complex cases than this I'd like to make fully thread-safe)
I could probably just put a lock(obj) round both the event handler and the body of the constructor, but that feels clumsy and I suspect it's probably prone to deadlock somehow.
Is there a clean & reliable way of doing this?
ECMA-335 doesn't obligate a CLI to provide guarantee that the initialization changes which are made in a constructor should be visible before the constructor completion:
It is explicitly not a requirement that a conforming implementation of the CLI guarantee that all state updates performed within a constructor be uniformly visible before the constructor completes (see there, section I.12.6.8).
So the brief answer: avoid a subscription of an instance event handlers inside a constructor because it implies an exposure of the instance to external consumers with no guarantee that the instance is ready for consumption.
In details: typically semantic of a constructor implies only state initialization that is getting internal data of an instance into consistent state (when all its invariants are true and it's ready for consumption by other objects). The mechanism of events in C# in essence is adaptation of observer pattern which implies number of interactions between its participants and making of subscription is one of those interactions and as any other interaction with other object it should be avoided in a constructor when the instance isn't guaranteed to be initialized. You correctly noticed the possible scenario when it can become a problem but even with applying of protection mechanisms like reordering or synchronization, it cannot be guaranteed 100% safe, because it may not be provided by a CLI implementation or even if provided there is still possibility of scenarios when a constructor fails to complete for a reason not dependent on code inside the constructor, for example because of ThreadAbortException.
Of course there can be some relaxed requirements to design dictated by some well-known constraints (for example you can be 100% sure that your event publisher is implemented in the way which excludes critical scenarios) but in general case I'd suggest to make separation of construction and subscription scenarios when there is separate method, which is part of public contract and which is purposed only for making subscriptions.
How about using a thread-safe collection (like ConcurrentQueue) combined with the null conditional operator?
Thread-safe delegate invocation
Use the ?. operator to check if a delegate is non-null and invoke it in a thread-safe way (for example, when you raise an event).
class MyClass
{
private ConcurrentQueue<string> changes;
public MyClass(INotifyPropertyChanged observable)
{
observable.PropertyChanged += this.Handler;
// Another thread changes a property at this point
this.changes = new ConcurrentQueue<string>();
}
private void Handler(object sender, PropertyChangedEventArgs e)
{
this.changes?.Enqueue(e.PropertyName);
// Nothing breaks, changes during construction are simply not recorded
}
}

Is it safe to raise the same event from multiple threads at once?

I've got an event that's invoked from multiple threads. The event handlers themselves expect this (they are thread-safe). But is the actual parallel invocation safe?
class Raiser
{
public static event Action E = delegate { };
public static void RaiseE()
{
// Called from many threads at once
E();
}
}
I imagine this is OK because the backing delegate list is immutable and the event object reference is atomically updated, but when it comes to multithreading I'd rather be sure than guess :-)
Yes; that is perfectly thread-safe.
However, if any of the handlers (or the methods they call) are not thread-safe, you will still have problems.
If this is a public API, you should clearly document which thread(s) the event may be raised on.

Remove event listener from local variable

Do I have to worry about removing event listeners assigned to local variables?
Consider the following sample:
var zipUtil = new ZipUtil();
zipUtil.ProgressChanged += ZipUtil_ProgressChanged;
I'm creating an instance of the ZipUtil class which is stored as a local variable within a method. Do I have to remove the listener (zipUtil.ProgressChanged -= ZipUtil_ProgressChanged;) before the method terminates or is it okay to skip the step?
No, you don't have to remove that event handling method.
When adding an event handler to an event, a reference from the (object containing the) event to the event handler is created, not the other way round. Once zipUtil goes out of scope, the event handler will not make any difference pertaining to references to zipUtil.
Two lines of code are never enough to make the call accurately. But it is very unlikely you'll need to unsubscribe explicitly. There are two possible problem scenarios:
the class may fire its event at an inopportune time, after your object is disposed for example. That's fairly unlikely in this scenario, surely the ZipUtil class stops raising ProgressChanged events when you stop calling its methods. Not completely out of the question, it could do work on a background thread for example. Not visible from your snippet.
you can have a garbage collection problem due to events. The event delegate keeps an implicit reference to your class object, necessary so it can call ZipUtil_ProgressChanged() method. If it is an instance method, not clear from your snippet. That reference will keep your outer class alive. But not the other way around. Given that the lifetime of the ZipUtil object is restricted to the method and you surely want your outer class to survive at least to the end of the method, this should never be a problem.
High odds that ZipUtil implements IDisposable btw. Do make sure you use the using statement if it does.

Marshalling Events Across Threads

I imagine this may be marked as repetitious and closed, but I cannot for the life of me find a clear, concise answer to this question. All the replies and resources deal almost exclusively with Windows Forms and utilizing pre-built utility classes such as BackgroundWorker. I would very much like to understand this concept at its core, so I can apply the fundamental knowledge to other threading implementations.
A simple example of what I would like to achieve:
//timer running on a seperate thread and raising events at set intervals
//incomplete, but functional, except for the cross-thread event raising
class Timer
{
//how often the Alarm event is raised
float _alarmInterval;
//stopwatch to keep time
Stopwatch _stopwatch;
//this Thread used to repeatedly check for events to raise
Thread _timerThread;
//used to pause the timer
bool _paused;
//used to determine Alarm event raises
float _timeOfLastAlarm = 0;
//this is the event I want to raise on the Main Thread
public event EventHandler Alarm;
//Constructor
public Timer(float alarmInterval)
{
_alarmInterval = alarmInterval;
_stopwatch = new Stopwatch();
_timerThread = new Thread(new ThreadStart(Initiate));
}
//toggles the Timer
//do I need to marshall this data back and forth as well? or is the
//_paused boolean in a shared data pool that both threads can access?
public void Pause()
{
_paused = (!_paused);
}
//little Helper to start the Stopwatch and loop over the Main method
void Initiate()
{
_stopwatch.Start();
while (true) Main();
}
//checks for Alarm events
void Main()
{
if (_paused && _stopwatch.IsRunning) _stopwatch.Stop();
if (!_paused && !_stopwatch.IsRunning) _stopwatch.Start();
if (_stopwatch.Elapsed.TotalSeconds > _timeOfLastAlarm)
{
_timeOfLastAlarm = _stopwatch.Elapsed.Seconds;
RaiseAlarm();
}
}
}
Two questions here; primarily, how do i get the event to the main thread to alert the interested parties of the Alarm event.
Secondarily, regarding the Pause() method, which will be called by an object running on the main thread; can i directly manipulate the Stopwatch that was created on the background thread by calling _stopwatch.start()/_stopwatch.stop(). If not, can the main thread adjust the _paused boolean as illustrated above such that the background thread can then see the new value of _paused and use it?
I swear, I've done my research, but these (fundamental and critical) details have not made themselves clear to me yet.
Disclaimer: I am aware that there are classes available that will provide the exact particular functionality that I am describing in my Timer class. (In fact, I believe the class is called just that, Threading.Timer) However, my question is not an attempt to help me implement the Timer class itself, rather understand how to execute the concepts that drive it.
Note: im writing this here because theres not enough space on comments, this is of course not a complete, nor half a complete answer:
I've always used Events to signal unrelated code to do something, so that was how I described my intent. Forgive me though, I'm not sure I see the difference between marshaling and event versus marshaling another type of data (signal).
Conceptually both can be treated as events. The difference between using provided sync/signalining objects and trying to implement something like this by urself, is who and how gets the job done.
An event in .net is just a delegate, a list of pointers to methods that should be executed when the provider of the event fires it.
What youre talking about (marshalling the event), if i understand you correctly, is sharing the event object when something happens, while the concept of signalig usually talks about an object which is shared to start with, and both threads "know" something happened by checking its state either manualy or automatily (relying on provided tools by both .net and windows).
In the most basic scenario, you can implement such a signaling concept by using a boolean variable, with one thread constantly looping to check if the value of the boolean is true, and another setting to such, as a way to signal something happend. The different signaling tools provided by .NET do this in a less resource-wasting maner, by also not executing the waiting thread, as long as theres no signal (the boolean equals to false), but conceptually, it is the same idea.
You cannot magically execute code on an existing thread.
Instead, you need the existing thread to explicitly execute your code, using a thread-safe data structure to tell it what to do.
This is how Control.Invoke works (which is in turn how BackgroundWorker works).
WiinForms runs a message loop in Application.Run() which looks roughly like this:
while(true) {
var message = GetMessage(); //Windows API call
ProcessMessage(message);
}
Control.Invoke() sends a Windows message (using thread-safe message passing code within Windows) telling it to run your delegate. ProcessMessage (which executes on the UI thread) will catch that message and execute the delegate.
If you want to do this yourself, you will need to write your own loop. You can use the new thread-safe Producer-Consumer collections in .Net 4.0 for this, or you can use a delegate field (with Interlocked.CompareExchange) and an AutoResetEvent and do it yourself.

How Can I Get an Event Handler to be Called From a Seperate Thread than the One it Was Created On?

I'm having some trouble getting a web-page indexing program to work. I have a form that automatically downloads URLs to index from a database server and sends back responses containing the indexed page information, over UDP. I have a static class called UDP that keeps track of incoming and outgoing messages. There is an event that fires whenever a message is recieved, which the form that contains all the indexing code hooks to keep track of messages sent from a program on the server that holds the database of urls to index.
This was all working fine, until I added another form that appears before the indexing form. Now, the indexing form opens on another thread (through Application.Run() and a second thread). The problem is, the event handler is no longer called when the event is fired.
So, the question is, what is going on here, and what can I do to fix it? I'm pretty sure it has to do with some cross-thread safety mechanism that doesn't call event handlers on another thread than the one the event was fired from. Does anybody know of a different way to do this or a way to circumvent this? Thanks in advance...
An UI control has to be manipulated on the thread that it was created on (the UI thread).
In order to achieve that, you'll have to 'invoke' the event-handler.
This can be done by raising the event like this:
EventHandler handler = myEventHandler;
if( handler != null )
{
ISynchronizeInvoke target = handler.Target as ISynchronizeInvoke;
if( target != null && target.InvokeRequired )
{
target.Invoke (handler, ... );
}
else
{
handler.DynamicInvoke (...);
}
}
Or, you can also have a look at the AsyncOperation & AsyncOperationManager classes.
Or, perhaps even simpler, take a look at the SynchronizationContext class. Using the 'Current' property of this class, you can just Post a SendOrPostCallback delegate which wraps around your eventhandler.
I don't think this is a "safety mechanism". The safety mechanism that does exist in WinForms (from .NET 2.0 onwards) throws an exception if you're in the debugger and you try to access the UI from a thread other than the appropriate one.
Are you sure that the event isn't being called at all? That sounds extremely strange. If you put a breakpoint on the event handler in the debugger, does that break point not get hit?
To answer your question in a different way though, I wouldn't make the entire event handler execute on a specific thread. There may be more than one handler subscribed, and those handlers may need to execute on different threads. Instead, I would make the event handlers themselves thread-safe - code them so that if they need to perform some action on a particular thread, they do the marshalling back to the thread (e.g. with Control.BeginInvoke etc).
Which thread is most of your network access taking place on? I would hope it's not either of the UI threads involved (as otherwise you can get an unresponsive UI). That would mean that if it was working before, you're probably already doing the appropriate marshalling... very strange.
If none of this helps, could you try to come up with a short but complete program which demonstrates the problem? It's easier to diagnose concrete code :)

Categories