Looking for an example of a custom SynchronizationContext (Required for unit testing) Looking for an example of a custom SynchronizationContext (Required for unit testing) multithreading multithreading

Looking for an example of a custom SynchronizationContext (Required for unit testing)


This one was written by me some time ago, no issues with copyright, no guarantees either(the system didn't go into production):

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;using System.Windows.Threading;namespace ManagedHelpers.Threads{    public class STASynchronizationContext : SynchronizationContext, IDisposable    {        private readonly Dispatcher dispatcher;        private object dispObj;        private readonly Thread mainThread;        public STASynchronizationContext()        {            mainThread = new Thread(MainThread) { Name = "STASynchronizationContextMainThread", IsBackground = false };            mainThread.SetApartmentState(ApartmentState.STA);            mainThread.Start();            //wait to get the main thread's dispatcher            while (Thread.VolatileRead(ref dispObj) == null)                Thread.Yield();            dispatcher = dispObj as Dispatcher;        }        public override void Post(SendOrPostCallback d, object state)        {            dispatcher.BeginInvoke(d, new object[] { state });        }        public override void Send(SendOrPostCallback d, object state)        {            dispatcher.Invoke(d, new object[] { state });        }        private void MainThread(object param)        {            Thread.VolatileWrite(ref dispObj, Dispatcher.CurrentDispatcher);            Console.WriteLine("Main Thread is setup ! Id = {0}", Thread.CurrentThread.ManagedThreadId);            Dispatcher.Run();        }        public void Dispose()        {            if (!dispatcher.HasShutdownStarted && !dispatcher.HasShutdownFinished)                dispatcher.BeginInvokeShutdown(DispatcherPriority.Normal);            GC.SuppressFinalize(this);        }        ~STASynchronizationContext()        {            Dispose();        }    }}


idesign.net (search for Custom Synchronization Context on the page) has a SynchronizationContext that will do the job, however it is more complex them I need.


Had a similar requirement - unit testing a server component to confirm that it's callback delegate invocations were marshalled onto an appropriate SynchronizationContext and came up with the following code (based on Stephen Toub's blog post http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx) which I recon is simpler and more general as it uses it's own internal thread to service the Post()/Send() requests, rather than relying on WPF/Winforms/.. to perform dispatching.

    // A simple SynchronizationContext that encapsulates it's own dedicated task queue and processing    // thread for servicing Send() & Post() calls.      // Based upon http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx but uses it's own thread    // rather than running on the thread that it's instanciated on    public sealed class DedicatedThreadSynchronisationContext : SynchronizationContext, IDisposable    {        public DedicatedThreadSynchronisationContext()        {            m_thread = new Thread(ThreadWorkerDelegate);            m_thread.Start(this);        }        public void Dispose()        {            m_queue.CompleteAdding();        }        /// <summary>Dispatches an asynchronous message to the synchronization context.</summary>        /// <param name="d">The System.Threading.SendOrPostCallback delegate to call.</param>        /// <param name="state">The object passed to the delegate.</param>        public override void Post(SendOrPostCallback d, object state)        {            if (d == null) throw new ArgumentNullException("d");            m_queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state));        }        /// <summary> As         public override void Send(SendOrPostCallback d, object state)        {            using (var handledEvent = new ManualResetEvent(false))            {                Post(SendOrPostCallback_BlockingWrapper, Tuple.Create(d, state, handledEvent));                handledEvent.WaitOne();            }        }        public int WorkerThreadId { get { return m_thread.ManagedThreadId; } }        //=========================================================================================        private static void SendOrPostCallback_BlockingWrapper(object state)        {            var innerCallback = (state as Tuple<SendOrPostCallback, object, ManualResetEvent>);            try            {                innerCallback.Item1(innerCallback.Item2);            }            finally            {                innerCallback.Item3.Set();            }        }        /// <summary>The queue of work items.</summary>        private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> m_queue =            new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>();        private readonly Thread m_thread = null;        /// <summary>Runs an loop to process all queued work items.</summary>        private void ThreadWorkerDelegate(object obj)        {            SynchronizationContext.SetSynchronizationContext(obj as SynchronizationContext);            try            {                foreach (var workItem in m_queue.GetConsumingEnumerable())                    workItem.Key(workItem.Value);            }            catch (ObjectDisposedException) { }        }    }