Many of us may be familiar with the restriction against modifying a Control from any thread other than the one in which it was created, if we do so we get a CrossThreadOpeartionException. Instead, an event generated on another thread must be marshaled to the Control’s thread using its (or the Form that it belongs to) Invoke or BeginInvoke methods. These two methods belong to the ISynchronizeInvoke interface, which the Control class implements. Their purpose is to take a delegate and invoke it on the same thread that the ISynchronizeInvoke object is running. Have a look at this tip by Rabinarayan Biswal
In the above tip, the method DisplayErrorOnUI() first checks its InvokeRequired boolean property, which also belongs to the ISynchronizeInvoke interface, to see if it needs to marshal the event to its thread. If the property is true, it calls the BeginInvoke method, passing it a delegate to the method for handling the event and its arguments. If the property is false, it executes its logic for responding to the event. In other words, the InvokeRequired property will be true if it is checked on a thread other than the one in which the Form belongs; otherwise, it will be false.
But, wouldn’t it be nice if Forms didn’t have to check to see if an event was raised on another thread? Wouldn’t it be nice if a Form could respond to an event without having to check its InvokeRequired property? This is the place where SynchronizationContext class comes to our rescue.
The SynchronizationContext class gives us a way through which we can pass delegates to be invoked on the same thread that the SynchronizationContext represents. It is like the ISynchronizeInvoke interface in that respect. Corresponding to the ISynchronizeInvoke’s Invoke and BeginInvoke methods, the SynchronizationContext class has Send and Post methods. Like the Invoke method, the SynchronizationContext’s Send method is for invoking delegates synchronously, and like the BeginInvoke method, the Post method is for invoking delegates asynchronously.