Event handlers and multithreading in .NET framework - c#

Can event handlers like FileSystemEventHandler related to FileSystemWatcher class be called from the different threads at the same time (parallel to each other)? Is there any guarantees about it at all?

In general, there are no guarantees.
The event handler runs on the same thread it is invoked on, but that doesn't really tell you anything - for all you know, it could be invoked with something like ThreadPool.QueueUserWorkItem(() => EventHandler()). System.Timers.Timer is one example - the timer callbacks are invoked on a thread pool thread, and multiple can run in parallel.
The major exception are events used in terms of some synchronization context - for example, GUI events (including System.Windows.Forms.Timer) in Windows Forms will only ever launch on the GUI thread. However, the documentation should explicitly specify that the event handlers have some particular thread affinity - it certainly isn't the default assumption.
FileSystemWatcher in particular is even trickier. If it has a SynchronizingObject set, it will have thread affinity - the handlers will be invoked on the synchronizing object. If that synchronizing object is a Form, for example, the handler will always run on the GUI thread and it will never run in parallel. Other synchronizing objects may behave differently (you could always make your own synchronizing object that posts the delegate to the thread pool, for example). Note that the invocation is asynchronous - it does BeginInvoke, not Invoke - so it can very much result in parallel execution if your synchronizing object does something like ThreadPool.QueueUserWorkItem.
If there is no synchronizing object, the handler runs on the same thread that received the notification. Since FileSystemWatcher runs on a IOCP, it's pretty safe to assume that it's just borrowing a threadpool thread for the duration of the callback. However, it also explicitly locks around the whole code, including the event handler invocation - so it will not run in parallel.

The add and remove handlers of the FileSystemWatcher class are nothing special so - as in most cases - it is completely indifferent, from which thread you subscribe a method. If you set the FileSystemWatcher.SynchronizingObject, the delegate will be invoked on that object by a BeginInvoke call; otherwise,
it will be invoked in the tread where your FileSystemWatcher resides.
The methods of a delegate will be called after each other in the thread of the invoker, so there is no syncing issue among them. However, if in your other threads you use common resources with the subscribed methods, you must take care of syncing as usual.

Related

In the execution of a program, are events like threads? WPF

I have a background worker thread continuously updating the data displayed in a window from a network source. I also have a button which will fire an event.
My question is, at what stage (relative to the background worker execution) is the event method executed? Is it similar to threads in that they happen simultaneously? I.e, will the background worker will still be running whilst my button click method is executing? In which case, I will need to use locking. Or will the background worker pause until the button click method has terminated?
Events raised by UI controls (e.g. buttons) execute in the main thread, a.k.a. the UI thread. Events you raise yourself are raised on whatever thread you raise them on. All event raisings block the execution of their own thread until they complete. They're not very special, when you call them: Just a little syntactic sugar around calling an arbitrary list of delegates.
In the absence of any explicit synchronization code, any other threads humming along the background will merrily continue to execute.
If you need or want to communicate between an event handler in the UI thread and a worker thread, you'll need to write explicit code to do so. Nothing special here: Just two threads.
And if you've got both an event handler and a thread putting their greasy little mitts on the same object, and if the operations on that object are not atomic, you're correct: You'll need locking. Thread-safe collections may come in handy.

Wait method not taking up resources

How can a thread blocking method like WaitOne method exposed by AutoResetEvent not take up resources (CPU etc.)?
I would imagine that such a method would simply have a while loop like:
public void WaitOne()
{
while(IsSet == false)
{
// some code to make the thread sleep
}
// finally call delegate
}
But that's clearly wrong, since it will make the CPU spin. So what's the secret behind all this black magic?
The method is implemented in the kernel. For each thread that isn't ready to run, Windows keeps a list of all the waitable objects (events, etc.) that the thread is waiting on. When a waitable object is signalled, Windows checks if it can wake up any of the waiting threads. No polling required.
This channel9 talk has a lot of information about how it works:
http://channel9.msdn.com/shows/Going+Deep/Arun-Kishan-Farewell-to-the-Windows-Kernel-Dispatcher-Lock/
Typically, these concepts rely on underlying operating system event constructs to wake up the suspended thread once the event is triggered (or a timeout occurs if applicable). Thus, the thread is in a suspended state and not consuming CPU cycles.
That said, there are other variations of wait in other event types, some of which attempt to spin for a few cycles before suspending the thread in case the event is triggered either before or quickly after the call. There are also some lightweight locking primitives that DO perform spins waiting for a trigger (like SpinWait) but they must be used with care as long waits can drive up the CPU.
The AutoResetEvent and ManualResetEvent take advantage of OS functions. See CreateEvent for more information on this topic.

Does System.Timers.Timer uses a seprate thread to execute timer_elapsed method

I am using Systems.Timers.Timer instance in a windows service. My question is that whatever is been in its Timer_Elapsed method, does that code get executed in the same thread where windows service is been run or does Timer internally execute elapsed method on a separate thread?
A recent blog post by Abhishek Sur can answer your question.
In summary, System.Timers.Timer:
It invokes the available thread in ThreadPool to run the interface.
ThreadSafe, each eventhandler has explicit locks.
Can be run in any thread using ISynchronizeObject.
Yes - but exactly which is a little complex (see MSDN):
If the SynchronizingObject property is null, the Elapsed event is raised on a ThreadPool thread. If processing of the Elapsed event lasts longer than Interval, the event might be raised again on another ThreadPool thread. In this situation, the event handler should be reentrant.
But either way; it isn't your thread - code appropriately, with synchronization.
The Elapsed event handlers will be executed on another thread, not the thread that started the service unless you manually specify a synchronization object to provide a synchronization context.
This is primarily targeted for Windows Forms applications, where System.Windows.Forms.Control (and all derived types, such as Form) implement the ISynchronizeInvoke interface and can be easily attached to the timer in order to synchronize execution. In a Windows Service environment, you'll have to code up a stub implementation of that interface that does the necessary thread synchronization, since the service provides no such implementation itself.

BackgroundWorker component in services

I know the BackgroundWorker should not be used in Windows Services but would anyone have a good online reference explaining why?
BackgroundWorker relies on a current SynchronizationContext being set in order to function. It's really intended and designed specifically for working with UI code.
It's typically better in a service to self-manage your threads, since there are no UI synchronization issues. Using the threading API (or .NET 4 Task API) is a much better option here.
Well, it's okayish to use a BGW in a service, it just doesn't do anything especially useful. Its reason for being is its ability to raise the ProgressChanged and RunWorkerCompleted events on a specific thread. Getting code to run on a specific thread is a very non-trivial thing to do. You cannot simply inject a call into the thread while it is executing code. That causes horrible re-entrancy problems. The thread has to be 'idle', in a state where inject code doesn't cause trouble.
Having a thread in an idle state is a fairly unnatural condition. You use threads to run code, not for them to be idly spinning its heels. This is however the way a UI thread works. It spends 99% of its time in the message loop, waiting for Windows to tell it to do something. A button click, a paint request, a keyboard press, that sort of thing. While it is inside the message loop, it is in fact idle. A very good time to execute injected code.
Which is what Winforms' Control.Begin/Invoke and WPF's Dispatcher.Begin/Invoke do. They put a delegate in a queue, the queue is emptied and the delegate targets executed by the message loop. The WindowsFormsSynchronizationContext and DispatcherSynchronizationContext classes are the synchronization providers that uses them. Winforms and WPF replace SynchronizationContext.Current with an instance of them. Which in turn gets used by BGW to raise the events. Which makes them run on the UI thread. Which allows you to update the non thread-safe user interface components from a worker thread.
You can probably see where this is heading, a service uses neither. The default synchronization provider doesn't synchronize anything. It simply uses a threadpool thread to call the Send or Post callback. Which is what will happen when you use BGW in a service. Now there is actually no point at all in having these events. You might as well let the DoWork handler call the event handling methods directly. After all, the thread on which DoWork runs is just another threadpool thread as well.
Well, no real harm done, other than making it quite a bit slower.
I've used BackgroundWorker in windows services many times without any ill effect. While its use of SynchronizationContext may be unnecessary, I haven't observed it causing problems or poor performance.

Raising events asynchronously

I'm looking into options for doing asynchronous event dispatching in a component that has many subscribers to its events. In perusing the options, I ran across this example:
public event ValueChangedEvent ValueChanged;
public void FireEventAsync(EventArgs e)
{
Delegate[] delegates = ValueChanged.GetInvocationList();
foreach (Delegate d in delegates)
{
ValueChangedEvent ev = (ValueChangedEvent)d;
ev.BeginInvoke(e, null, null);
}
}
Beyond the older syntax (the sample was from .NET 1.1), it looks to me like this is a serious resource leak. There's no completion method, no polling for completion, or any other way that EndInvoke will be called.
My understanding is that every BeginInvoke must have a corresponding EndInvoke. Otherwise there are pending AsyncResult object instances floating around, along with (potentially) exceptions that were raised during the asynchronous events.
I realize that it's easy enough to change that by supplying a callback and doing an EndInvoke, but if I don't need to . . .
Handling the asynchronous exeptions is another matter entirely, and, combined with the need to synchronize with the UI thread (i.e. InvokeRequired, etc.) could very well tank the whole idea of doing these asynchronous notifications.
So, two questions:
Am I correct in believing that every BeginInvoke requires a corresponding EndInvoke?
Beyond what I've noted above, are there other pitfalls to doing asynchronous event notifications in Windows Forms applications?
A call to BeginInvoke() should be paired with a EndInvoke() but not doing it will not result in a resource leak. The IAsyncResult returned by BeginInvoke() will be garbage collected.
The biggest pitfall in this code is you are highly exposed to exceptions terminating the application. You might want to wrap the delegate invocation in an exception handler and put some thought into how you want to propagate the exceptions that happen (report the first, produce an aggregate exception, etc).
Invoking a deletage using BeginInvoke() will take a thread off the thread queue to start running the event. This means that the event will always fire off the main UI thread. This might make some event handler scenarios harder to handle (e.g. updating the UI). Handlers would need to realize they need to call SynchronizationContext.Send() or .Post() to synchronize with the primary UI thread. Of course all other multi-thread programming pitfalls also apply.
After thinking about this for a while, I came to the conclusion that it's probably a bad idea to do asynchronous events in Windows Forms controls. Windows Forms events should be raised on the UI thread. Doing otherwise presents an undue burden on clients, and possibly makes a mess with AsyncResult objects and asynchronous exceptions.
It's cleaner to let the clients fire off their own asynchronous processing (using BackgroundWorker or some other technique), or handle the event synchronously.
There are exceptions, of course. System.Timers.Timer, for example, raises the Elapsed event on a thread pool thread. But then, the initial notification comes in on a pool thread. It looks like the general rule is: raise the events on the same thread that got the initial notification. At least, that's the rule that works best for me. That way there's no question about leaking objects.
No. EndInvoke is only required if a return type is specified. Check this out:thread. Also, I posted this thread which is semi related.
I really cant help you with that one! :-) sorry.

Categories

Resources