public static SingleThreadSynchronizationContext CreateInNewThread(LateArrivalBehavior lateArrivalBehavior, string threadName)
        {
            var tcs = new TaskCompletionSource <SingleThreadSynchronizationContext>();

#if DESKTOP
            var thread = new Thread(() =>
            {
                try
                {
                    Run(() =>
                    {
                        tcs.TrySetResult((SingleThreadSynchronizationContext)SynchronizationContext.Current);
                        return(new TaskCompletionSource <bool>().Task);
                    }, lateArrivalBehavior);
                }
                catch (Exception ex)
                {
                    tcs.TrySetException(ex);
                }
            });
            if (threadName != null)
            {
                thread.Name = threadName;
            }
            thread.IsBackground = true;
#if !CORECLR
            thread.SetApartmentState(ApartmentState.STA);
#endif
            thread.IsBackground = true;
            thread.Start();
#else
            Task.Run(() =>
            {
                try
                {
                    Run(() =>
                    {
                        tcs.TrySetResult((SingleThreadSynchronizationContext)SynchronizationContext.Current);
                        return(new TaskCompletionSource <bool>().Task);
                    }, lateArrivalBehavior);
                }
                catch (Exception ex)
                {
                    tcs.TrySetException(ex);
                }
            });
#endif
            tcs.Task.Wait();
            return(tcs.Task.Result);
        }
        private static void Run(Func <Task> func, LateArrivalBehavior lateArrivalBehavior, Action onFirstLateArrival)
        {
            if (func == null)
            {
                throw new ArgumentNullException("func");
            }

            var prevCtx = SynchronizationContext.Current;

            var syncCtx = new SingleThreadSynchronizationContext();

            try
            {
                syncCtx.Thread             = Thread.CurrentThread;
                syncCtx.onFirstLateArrival = onFirstLateArrival;
                //Console.WriteLine("Running " + syncCtx.GetHashCode() + " on thread " + Environment.CurrentManagedThreadId);
                syncCtx.lateArrivalBehavior = lateArrivalBehavior;
                SynchronizationContext.SetSynchronizationContext(syncCtx);

                var t = func();
                if (t == null)
                {
                    throw new InvalidOperationException("No task provided.");
                }
                t.ContinueWith(delegate
                {
                    try
                    {
                        var q = syncCtx.m_queue;
                        if (q != null)
                        {
                            q.CompleteAdding();
                        }
                    }
                    catch
                    {
                        // TODO should we do something here? can it happen?
                        //Console.WriteLine("Perdindirindina");
                    }
                    syncCtx.completed = true;
                }, TaskScheduler.Default);
                syncCtx.RunOnCurrentThread();
                if (!syncCtx.aborted)
                {
                    t.GetAwaiter().GetResult();
                }
                if (syncCtx.aborted)
                {
                    throw new OperationCanceledException("The SingleThreadSynchronizationContext was aborted.");
                }
            }
            finally
            {
                SynchronizationContext.SetSynchronizationContext(prevCtx);

                var q = syncCtx.m_queue;
                if (q != null)
                {
                    q.Dispose();
                }
                syncCtx.m_queue = null;

                var d = syncCtx.drainingCompletion;
                if (d != null)
                {
                    d.TrySetResult(true);
                }
            }
        }
 public static void Run(Func <Task> func, LateArrivalBehavior lateArrivalBehavior)
 {
     Run(func, lateArrivalBehavior, null);
 }
 public static SingleThreadSynchronizationContext CreateInNewThread(LateArrivalBehavior lateArrivalBehavior)
 {
     return(CreateInNewThread(lateArrivalBehavior, null));
 }