What happen internally when we call BeginInvoke on a variable of delegate type?
This depends on the type of object in which you call BeginInvoke.
ISynchronizeInvoke is the interface that defines BeginInvoke. It passes the delegate to the object that implements that interface, and that object will (should) schedule the thread to run on it's own main thread.
There are a few objects that implement this interface. The Dispatcher in WPF does this - when you call BeginInvoke on the dispatcher, the delegate is added to the dispatcher's queue, and run when it is appropriate.
The Control base class in Windows Forms also implements ISynchronizeInvoke (and I believe this may be what your question was hinting at). In Windows Forms, things are much more complicated. Here is a great article explaining the details. Basically, what happens when you call BeginInvoke on a winforms control is that a special marshaller creates a windows message that is passed to the program, and the UI thread queues the delegate to be run. It's a bit more complex than that (as that article describes), but that's the basic idea. The delegate is then run on the main UI thread.
There are other objects that implement ISynchronizeInvoke, but most of them are objects that are managing and running their own thread. These objects maintain a queue of delegates, and add yours to that queue so it runs on their thread.
Related
The following article states the following regarding the BindingOperations.EnableCollectionSynchronization method:
To use a collection on multiple threads, one of which is the UI thread
that owns the ItemsControl, an application has the following
responsibilities:
Choose a synchronization mechanism.
Synchronize all access from the application to the collection using
that mechanism.
Call EnableCollectionSynchronization to inform WPF of the mechanism.
The call must occur on the UI thread.
The call must occur before using the collection on a different thread
or before attaching the collection to the ItemsControl, whichever is
later.
Call the EnableCollectionSynchronization(IEnumerable, Object) overload
if using a simple lock mechanism; call the
EnableCollectionSynchronization(IEnumerable, Object,
CollectionSynchronizationCallback) overload if using a more elaborate
mechanism.
Specifically it says "The call must occur on the UI thread."
My question is what happens if you do not call it from the UI thread?
What are the possible side effects?
Exactly what the question says.
I've read the MSDN article given here, and (unless I'm blind), can't see anywhere where it explicity confirms this.
To give more scope, I'm mainly referring to the Socket.Beginxxx methods provided in the Socket class.
Is it safe for me to assume that any AsyncCallbacks will be executed in the main thread? Assume any Socket.Beginxxx methods I call will also be called from the main thread.
EDIT: If this is not the case, should I lock private members of the containing class when I modify them in one of the Socket.Beginxxx AsyncCallbacks? E.g. adding an item to a dictionary?
I've read the MSDN article given here, and (unless I'm blind), can't see anywhere where it explicity confirms this.
The relevant quote is (emphasis added):
Use an AsyncCallback delegate to process the results of an asynchronous operation in a separate thread.
The callback is not guaranteed to execute in the originating thread; in fact, it is guaranteed to run on another thread (i.e., a thread pool thread).
In spite of the other answers, this has absolutely nothing to do with SynchronizationContext or how TAP or EAP work with their contexts. AsyncCallback is part of APM - the oldest asynchronous pattern - which does absolutely no automatic thread marshaling for you.
If this is not the case, should I lock private members of the containing class when I modify them in one of the Socket.Beginxxx AsyncCallbacks? E.g. adding an item to a dictionary?
You could. I have found in my asynchronous socket code that it's easier to marshal all the callbacks back to a single shared thread which is responsible for all socket operations and related data. Then no locks are necessary because all the "completed events" are synchronized to a single thread.
No. Your assumption does not always hold. Some frameworks may override the override the synchronization context to invoke continuations on a specific thread, but there is no guarantee at language-level. Here's what Stephen Toub says about it (in a very informative post on the subject):
frameworks can derive their own context from SynchronizationContext and override the Post method to be more appropriate to the scheduler being represented. In the case of Windows Forms, for example, the WindowsFormsSynchronizationContext implements Post to pass the delegate off to Control.BeginInvoke. For DispatcherSynchronizationContext in WPF, it calls to Dispatcher.BeginInvoke. And so on.... That’s how await “brings you back to where you were.”
With an unchanged SychronizationContext (such as with a console app), the continuations will be queued to the ThreadPool, and so effectively, it could run on any thread.
When I received an exception that is related with thread context, I use delegate function and I invoke this delegate function. It is necessary for use control from an other thread. But I've just learned that I can use SynchronizationContext.Post() function and I can call my delegate in this method.
I'm not sure which one is better? What are differences between these methods?
It is the same thing, SynchronizationContext.Post() calls BeginInvoke() and Send() calls Invoke().
The key property of SynchronizationContext is that there is more than one implementation of it. Important ones are WindowsFormsSynchronizationContext, it uses Control.Begin/Invoke and DispatcherSynchronizationContext, it uses Dispatcher.Begin/Invoke. There are others for ASP.NET, Windows Store (aka WinRT, aka Universal) apps, out-of-process servers that are COM+ hosted, etcetera.
The extra level of indirection helps avoid taking a dependency on the specific method that invokes. Important for any class library of course.
Control.Invoke is equivalent to SynchronizationContext.Send in that both are synchronous. Control.BeginInvoke is equivalent to SynchronizationContext.Post in that both are asynchronous. Use any of these 4 methods to prevent a cross-thread exception.
Use SynchronizationContext to encapsulate thread marshaling code. For example, Form1 creates object Worker to do some work on a different thread. The constructor for Worker captures the current (i.e. Form1's) SynchronizationContext. When Worker produces data to display on Form1, Worker can use the captured SynchronizationContext to synchronize to Form1's thread before sending a notification, e.g. event, to Form1. This means that Form1 does not need to know about the different thread, does not need to call InvokeRequired, and has less code. It also means that Worker does not need to know that its client is a Form.
Below is an excellent series explaining SynchronizationContext:
Understanding SynchronizationContext - Part I
Understanding SynchronizationContext - Part II
Understanding SynchronizationContext - Part III
I have a System.Timers.Timer object, and within its Elapsed method I want to call myObject.TriggerEvent(...), but I want that invocation to happen on the thread myObject was created on. Is there an easy way to do this? And is this a bad idea for any reason? myObject is basically an event manager service, so I want it to trigger events on the thread it was created on. The reason I'm using the timer is because I have another that is polling a service for updates, which it notifies myObject of via the TriggerEvent method.
You can make your own SynchronizationContext implementation and provide its instance to the caller of myObject.TriggerEvent. If you're using myObject in WPF, SL or WinForms application, you can use their existing implementations of SynchronizationContext class and create myObject on the GUI thread.
I would recommend using a Dispatcher. It was created in the context of WPF, but there is no reason it can't be used elsewhere. I've used it in a couple of times, but I always had a message pump (Win32), but I believe that it can be used in service contexts as well (IIS, etc) - however I have not written such code, so YMMV. This is a good article from a WPF angle.
Erick
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.