Part II: Mimic SynchronizationContext behaviour on .NET CF

Not long ago I posted the first part of this article under:

Part I: Mimic SynchronizationContext behaviour on .NET CF

The article was intended to give the reader a better feeling of the purpose of the SynchronizationContext and the importance of the class on behalf of synchronization between different apartment threads. Unfortunately the SynchronizationContext is not available on the .NET compact framework which is especially annoying when you want to port existing code which uses the SynchronizationContext onto the compact framework platform. So how can we obtain similar functionality on the compact framework?

In that article I stated at the end that the behavior of the SynchronizationContext class can be summarized as the following:

We can briefly summarize that the purpose of the SynchronizationContext is to post (asynchronous) or send (synchronous) SendOrPostCallback delegates in the correct threading context which simplifies marshaling.

Coding this behavior into an interface in C# leads us to the following interface definition:

public interface ISynchronizationContext
    {        // Asynchronous
        void Post(SendOrPostCallback d, object state);
        // Synchronous
        void Send(SendOrPostCallback d, object state);
    }

The actual method which shall be executed in the context of the SynchronizationContext must comply to the following delegate type:

 public delegate void SendOrPostCallback(object state);

After the designing the interface of the SynchronizationContext we can easily implement the basic behavior of the general purpose SynchronizationContext via the usage of the .NET thread pool implementation on the compact framework:

public class SynchronizationContext : ISynchronizationContext
    {
        #region Implementation of ISynchronizationContext

        public void Post(SendOrPostCallback d, object state)
        {
            ThreadPool.QueueUserWorkItem(d.Invoke, state);
        }

        public void Send(SendOrPostCallback d, object state)
        {
            d(state);
        }

        #endregion
    }

The asynchronous posting of the SendOrPostCallback can be done by calling ThreadPool.QueueUserWorkItem. We simply pass in the SendOrPostCallback delegates Invoke() method which points to the bound method of the SendOrPostCallback delegate passing the state object along with the Invoke() method. On the other hand the synchronous send is easily achieved by simply invoking the past in SendOrPostCallback with the state object as parameter. That’s it!

But wait! Didn’t we mention a SynchronizationContext that is able to marshal calls to the current UI thread? YES we did! So how can we achieve this behavior on the compact framework? The trick behind the WindowsFormsSynchronizationContext is to implement the behavior of the ISynchronizationContext by instantiating an internal control in the context. This allows us to post the SendOrPostCallback via the controls BeginInvoke() and to send the SendOrPostCallback via the controls Invoke() method. Important to keep in mind is that the constructor must get the handle of the internally instantiated control! This forces the creation of the handle on the control if no handle exists. If this is not done the Invoke() or BeginInvoke() call leads to an exception of type InvalidOperationException.

public class WindowsFormsSynchronizationContext : ISynchronizationContext
    {
        #region Fields

        private readonly Control contextControl;

        #endregion

        #region Construction

        ///
        /// Initializes a new instance of the  class.
        ///
        public WindowsFormsSynchronizationContext()
        {
            contextControl = new Control();

            // Forces creation of the handle, this is important because the control is not visible!
            IntPtr handle = contextControl.Handle;
        }

        #endregion

        #region Implementation of ISynchronizationContext

        public void Post(SendOrPostCallback d, object state)
        {
            if (contextControl != null)
            {
                contextControl.BeginInvoke(d, new[] { state });
            }
        }

        public void Send(SendOrPostCallback d, object state)
        {
            if (contextControl != null)
            {
                contextControl.Invoke(d, new[] { state });
            }
        }

So we have now part of the SynchronizationContext behavior introduced on the compact framework. The only thing you need to do now is to implement some sort of “smart” factory which returns the right implementation of ISynchronizationContext either for windows forms operations or “normal” operations. This is left as exercise to the reader ;). Hope you enjoyed this journey into the deep darkness of the compact framework 😀

About the author

Daniel Marbach

4 comments

  • Hi, i also working with Compact Framework and found you blog post.
    Could you please tell me the last solution for the right smart factory, to get the current Thread?
    Something like the origin code:

    SynchronizationContext context = new SynchronizationContext.Current;

  • Hi,

    I think Stephen is referring that the implementation of SynchronizationContext does not include the “Current” member,
    so we are not able to implement it… I have the same problem 8-(

By Daniel Marbach

Recent Posts