public static Task Run(Func <Task> asyncMethod)
        {
            using (SynchronizationContextSwitcher.Capture())
            {
                var customContext = new Context();
                SynchronizationContext.SetSynchronizationContext(customContext);

                var task = asyncMethod.Invoke();

                if (task != null)
                {
                    // register a continuation with the task, which will shut down the loop when the task completes.
                    task.ContinueWith(_ => customContext.WorkQueue.Shutdown(), TaskContinuationOptions.ExecuteSynchronously);
                }
                else
                {
                    // the delegate returned a null Task (VB/C# compilers never do this for async methods)
                    // we don't have anything to register continuations with in this case, so just return immediately
                    return(task);
                }

                customContext.WorkQueue.ExecuteWorkQueueLoop();

                task.RethrowForCompletedTasks();

                return(task);
            }
        }
        /// <summary>
        /// Runs the action inside a message loop and continues looping work items
        /// as long as any asynchronous operations have been registered
        /// </summary>
        public static void Run(Action asyncAction)
        {
            using (SynchronizationContextSwitcher.Capture())
            {
                var customContext = new VoidContext();
                SynchronizationContext.SetSynchronizationContext(customContext);

                // Do an explicit increment/decrement.
                // Our sync context does a check on decrement, to see if there are any
                // outstanding asynchronous operations (async void methods register this correctly).
                // If there aren't any registerd operations, then it will exit the loop
                customContext.OperationStarted();
                try
                {
                    asyncAction.Invoke();
                }
                finally
                {
                    customContext.OperationCompleted();
                }

                customContext.WorkQueue.ExecuteWorkQueueLoop();
                // ExecuteWorkQueueLoop() has returned. This must indicate that
                // the operation count has fallen back to zero.
            }
        }