Basic, single-threaded implementation of SynchronizationContext I am trying to write a SynchronizationContext in C# that represents a message queue, to be pumped from a main loop.

Edit: I see that I have forgotten to say - I need the message loop executions to be done a single, pre-determined thread. (In my case I want to push updates to an OpenGL context.)

Here is the class I have written:

public class SingleThreadedSynchronizationContext : SynchronizationContext
{
    private sealed class WorkItem
    {
        private readonly SendOrPostCallback _callback;
        private readonly object _state;
        private readonly ManualResetEventSlim _reset;

        public WorkItem (SendOrPostCallback callback, object state, ManualResetEventSlim reset)
        {
            if (callback == null)
                throw new ArgumentNullException ("callback");

            _callback = callback;
            _state = state;
            _reset = reset;
        }

        public void Execute ()
        {
            _callback (_state);
            if (_reset != null) {
                _reset.Set (); 
            }
        }
    }

    private readonly ConcurrentQueue&lt;WorkItem&gt; _workItems = new ConcurrentQueue&lt;WorkItem&gt; ();
    private readonly Thread _executingThread;

    public SingleThreadedSynchronizationContext (Thread executingThread)
    {
        if (executingThread == null)
            throw new ArgumentNullException ("executingThread");
        _executingThread = executingThread;
    }

    internal bool HasWorkItems {
        get {
            return !_workItems.IsEmpty;
        }
    }

    private WorkItem ExecuteAndReturnNextWorkItem ()
    {
        WorkItem currentItem;
        if (_workItems.TryDequeue (out currentItem)) {
            currentItem.Execute ();
        }
        return currentItem;
    }

    private void ExecuteNextWorkItem ()
    {
        ExecuteAndReturnNextWorkItem ();
    }

    public override void Post (SendOrPostCallback d, object state)
    {
        _workItems.Enqueue (new WorkItem (d, state, null));
    }

    public override void Send (SendOrPostCallback d, object state)
    {
        if (Thread.CurrentThread == _executingThread) {
            WorkItem requestedWorkItem = new WorkItem (d, state, null);
            _workItems.Enqueue (requestedWorkItem);
            WorkItem executedWorkItem = null;
            do {
                executedWorkItem = ExecuteAndReturnNextWorkItem ();
            } while (executedWorkItem != null &amp;&amp; executedWorkItem != requestedWorkItem);
        } else {
            using (var reset = new ManualResetEventSlim ()) {
                _workItems.Enqueue (new WorkItem (d, state, reset));
                reset.Wait ();
            }
        }
    }
}


And here is a (everything additional removed) example of my main loop:

class MainClass
{
    public static void Main (string[] args)
    {
        var synchronizationContext = new CustomSynchronizationContext ();
        SynchronizationContext.SetSynchronizationContext (synchronizationContext);

        while (true) {
            // Do something else in my loop;

            while (synchronizationContext.HasWorkItems) {
                synchronizationContext.ExecuteNextWorkItem ();
            }
        }
    }


It is my first attempt at doing something on that level in the CLR concerning threading, so I wonder whether I have made any mistake in writing it, or done some other kind of mispractice (e.g. wrong class, etc.).
You don't need to implement Dispose pattern if you have no unmanaged resources to dispose. Unless you get paid per line of code, that is :)
You should not dispose objects you did not create (unless you implement a wrapper). In your case, you should not dispose reset event in WorkItem class, since you did not create it there. Instead, you should use

using(var reset = new ManualResetEventSlim())
{
    _workItems.Enqueue (new WorkItem (d, state, reset));
    ...
}

this code:

while (true) 
{
    synchronizationContext.Send(_ =&gt; Console.WriteLine("Hello!"), null)

    while (synchronizationContext.HasWorkItems) {
        synchronizationContext.ExecuteWorkItem ();
    }
}


will hang your application. You should either remove resetEvent from Send method and simply execute all queued WorkItems there (bad approach) or move this loop:

    while (synchronizationContext.HasWorkItems) {
        synchronizationContext.ExecuteWorkItem ();
    }


to sepatrate thread (better approach). Might look like:

public sealed class CustomSynchronizationContext : SynchronizationContext, IDisposable
{
     public CustomSynchronizationContext()
     {
         _thread = new Thread(() =&gt; 
               {
                   while(true)
                   {
                       _itemQueuedEvent.WaitOne();
                       if (_disposed) return;
                       ExecuteWorkItem();
                   }
               });
         _thread.Start();
     }

 ........
}


You will probably encounter some synchronization issues, but nothing that can not be solved.