Saturday, September 1, 2012

SynhronizationContext

Que-Why do we need synchronization context?
Ans-The idea behind synchronization context is that a "source" thread can queue a delegate(piece of work) to the target thread. Generally in STA model(like UI components) we can't have multiple threads modifying the same component. Thus its required that only a single thread, dedicated to update UI, will do this job. In order to achieve this kind of design, Synchronization context was introduced. In other words is does the following-
1) provide synchronization(by allowing only one operation by s single thread at a time)
2) Queuing a unit of work from one thread to another.

Que-Is Synchronization context only for UI element?
Ans-The original purpose of synchronization context is to update the UI elements only. We can have its use to pass any unit of work to other non-ui threads as well. (Yet to get more info).

Que-What is the different between send and post?
Ans- Send/post are 2 ways by which we can marshal the code from one thread to another. The difference is send is a synchronous call  whereas post is an Async call. Send will wait till the operation is completed and then will come back. The calling thread will be blocked until it returns.

Que- When we marshal a code to UI thread and that code throws exception, then who is responsible to catch that exception?
Ans -
In case of send method - It is caught at calling thread not on the UI thread.
in case of post - it is on ui thread only.

Here is the example-
This code is executed in a form application.
 public void Run(Object state)
        {
            Debug.WriteLine("Run Thread Id - " + Thread.CurrentThread.ManagedThreadId);
            SynchronizationContext context = state as SynchronizationContext;
            try
            {
                context.Send(UpdateUI,null);  
            }
            catch (Exception ex) {
                Debug.WriteLine(ex.ToString());
            }
        }

        public void UpdateUI(object state) {
            throw new Exception();
        }

        private void button1_Click(object sender, EventArgs e)
        {
           
            Debug.WriteLine("Main Thread Id - " + Thread.CurrentThread.ManagedThreadId);
            SynchronizationContext uiContext = SynchronizationContext.Current;

            Thread t1 = new Thread(Run);
            t1.Start(uiContext);
        }

Que- What will be the ThreadId of DoWork? Same as Run thread or main thread?
static void Main(string[] args)
        {
            Console.WriteLine("Main thread is " + Thread.CurrentThread.ManagedThreadId);
            SynchronizationContext context = new SynchronizationContext();           
            SynchronizationContext.SetSynchronizationContext(context);
            Thread t1 = new Thread(Run);
            t1.Start(SynchronizationContext.Current);
            Console.ReadLine();
        }

        static void Run(object state)
        {
            Console.WriteLine("Run Thread ID: " + Thread.CurrentThread.ManagedThreadId);
            var context = state as SynchronizationContext;
            context.Send(DoWork, null);
            while (true)
                Thread.Sleep(10000000);
        }
        static void DoWork(object state)
        {
            Console.WriteLine("DoWork Thread ID:" + Thread.CurrentThread.ManagedThreadId);
        }
Ans- It will be same as Run Thread. As We can't use Synchronization context in this way. Actually the Synchronization Context provided by .NET does have it message pump. context pushes the messages to this message pump then UI thread picks these messages from this queue or message pump. In the above case the message pump us missing. If we want to achieve similar behavior, then we will have to implement our own queue, and will have to read items on UI thread using that queue.

Que- What is message pump?
Ans - A message loop is a small piece of code that exists in any native Windows program. It roughly looks like this:
while(GetMessage(&msg, NULL, 0, 0))
{
   TranslateMessage(&msg);
   DispatchMessage(&msg);
}
The GetMessage() Win32 API retrieves a message from Windows.TranslateMessage() is a helper function that translates keyboard messages. DispatchMessage() ensures that the window procedure is called with the message.
In the recent version of windows the order of messages is maintained.

No comments:

Post a Comment