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)); }