public static TaskScheduler GetSynchronizationContext() { TaskScheduler taskScheduler = null; try { taskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); } catch {} if (taskScheduler == null) { try { taskScheduler = TaskScheduler.Current; } catch {} } if (taskScheduler == null) { try { var context = new CustomSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(context); taskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); } catch {} } return(taskScheduler); }
public async Task DefaultWriterSchedulerRunsOnSynchronizationContext() { SynchronizationContext previous = SynchronizationContext.Current; var sc = new CustomSynchronizationContext(); try { SynchronizationContext.SetSynchronizationContext(sc); using (var pool = new TestMemoryPool()) { var pipe = new Pipe( new PipeOptions( pool, resumeWriterThreshold: 32, pauseWriterThreshold: 64 )); Func <Task> doWrite = async() => { PipeWriter writableBuffer = pipe.Writer.WriteEmpty(64); ValueTask <FlushResult> flushAsync = writableBuffer.FlushAsync(); Assert.False(flushAsync.IsCompleted); await flushAsync; pipe.Writer.Complete(); Assert.Same(SynchronizationContext.Current, sc); }; Task writing = doWrite(); // Don't run on our bogus sync context ReadResult result = await pipe.Reader.ReadAsync().ConfigureAwait(false); pipe.Reader.AdvanceTo(result.Buffer.End, result.Buffer.End); Assert.Equal(1, sc.Callbacks.Count); sc.Callbacks[0].Item1(sc.Callbacks[0].Item2); pipe.Reader.Complete(); // Don't run on our bogus sync context await writing.ConfigureAwait(false); } } finally { SynchronizationContext.SetSynchronizationContext(previous); } }
public async Task FlushAsyncOnCompletedCapturesTheExecutionContextAndSyncContext(bool useSynchronizationContext) { var pipe = new Pipe(new PipeOptions(useSynchronizationContext: useSynchronizationContext, pauseWriterThreshold: 20, resumeWriterThreshold: 10)); SynchronizationContext previous = SynchronizationContext.Current; var sc = new CustomSynchronizationContext(); if (useSynchronizationContext) { SynchronizationContext.SetSynchronizationContext(sc); } try { AsyncLocal <int> val = new AsyncLocal <int>(); var tcs = new TaskCompletionSource <int>(); val.Value = 10; pipe.Writer.WriteEmpty(20); pipe.Writer.FlushAsync().GetAwaiter().OnCompleted(() => { tcs.TrySetResult(val.Value); }); val.Value = 20; // Don't run any code on our fake sync context ReadResult result = await pipe.Reader.ReadAsync().ConfigureAwait(false); pipe.Reader.AdvanceTo(result.Buffer.End); if (useSynchronizationContext) { Assert.Equal(1, sc.Callbacks.Count); sc.Callbacks[0].Item1(sc.Callbacks[0].Item2); } int value = await tcs.Task.ConfigureAwait(false); Assert.Equal(10, value); } finally { if (useSynchronizationContext) { SynchronizationContext.SetSynchronizationContext(previous); } pipe.Reader.Complete(); pipe.Writer.Complete(); } }
public void SynchronizationContextSwitching() { var context = new CustomSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(context); var test = _builder.BuildFrom(Method("AsyncVoidAssertSynchronizationContext")); var result = TestBuilder.RunTest(test, _testObject); Assert.AreSame(context, SynchronizationContext.Current); Assert.That(result.ResultState, Is.EqualTo(ResultState.Success), "Wrong result state"); Assert.That(result.AssertCount, Is.EqualTo(0), "Wrong assertion count"); }
public void SynchronizationContextSwitching() { var context = new CustomSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(context); var method = _builder.BuildFrom(Method(f => f.Yield())); var result = method.Run(new NullListener(), TestFilter.Empty); Assert.AreSame(context, SynchronizationContext.Current); Assert.That(result.Executed, Is.True, "Was not executed"); Assert.That(result.ResultState, Is.EqualTo(ResultState.Success), "Wrong result state"); Assert.That(result.AssertCount, Is.EqualTo(0), "Wrong assertion count"); }
public async Task ReadAsyncOnCompletedCapturesTheExecutionContext(bool useSynchronizationContext) { var pipe = new Pipe(new PipeOptions(useSynchronizationContext: useSynchronizationContext)); SynchronizationContext previous = SynchronizationContext.Current; var sc = new CustomSynchronizationContext(); if (useSynchronizationContext) { SynchronizationContext.SetSynchronizationContext(sc); } try { AsyncLocal <int> val = new AsyncLocal <int>(); var tcs = new TaskCompletionSource <int>(); val.Value = 10; pipe.Reader.ReadAsync().GetAwaiter().OnCompleted(() => { tcs.TrySetResult(val.Value); }); val.Value = 20; pipe.Writer.WriteEmpty(100); await pipe.Writer.FlushAsync(); if (useSynchronizationContext) { Assert.Equal(1, sc.Callbacks.Count); sc.Callbacks[0].Item1(sc.Callbacks[0].Item2); } int value = await tcs.Task; Assert.Equal(10, value); } finally { if (useSynchronizationContext) { SynchronizationContext.SetSynchronizationContext(previous); } pipe.Reader.Complete(); pipe.Writer.Complete(); } }
/// <summary> /// Executes a task synchronously on the calling thread by installing a temporary synchronization context that queues continuations /// </summary> public static void RunSync(Func <Task> task) { var currentContext = SynchronizationContext.Current; var customContext = new CustomSynchronizationContext(task); try { SynchronizationContext.SetSynchronizationContext(customContext); customContext.Run(); } finally { SynchronizationContext.SetSynchronizationContext(currentContext); } }
public static void RunSync(Func<Task> task) { var currentContext = SynchronizationContext.Current; var customContext = new CustomSynchronizationContext(task); try { SynchronizationContext.SetSynchronizationContext(customContext); customContext.Run(); } finally { SynchronizationContext.SetSynchronizationContext(currentContext); } }
public async Task DefaultReaderSchedulerIgnoresSyncContextIfConfigureAwaitFalse() { // Get off the xunit sync context var previous = SynchronizationContext.Current; try { var sc = new CustomSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(sc); var pipe = new Pipe(); Func <Task> doRead = async() => { ReadResult result = await pipe.Reader.ReadAsync().ConfigureAwait(false); Assert.True(Thread.CurrentThread.IsThreadPoolThread); pipe.Reader.AdvanceTo(result.Buffer.End, result.Buffer.End); pipe.Reader.Complete(); }; // This needs to run on the current SynchronizationContext Task reading = doRead(); PipeWriter buffer = pipe.Writer; buffer.Write(Encoding.UTF8.GetBytes("Hello World")); // We don't want to run any code on our fake sync context await buffer.FlushAsync().ConfigureAwait(false); // Nothing posted to the sync context Assert.Equal(0, sc.Callbacks.Count); pipe.Writer.Complete(); // We don't want to run any code on our fake sync context await reading.ConfigureAwait(false); } finally { SynchronizationContext.SetSynchronizationContext(previous); } }
public async Task DefaultReaderSchedulerRunsOnSynchronizationContext() { SynchronizationContext previous = SynchronizationContext.Current; var sc = new CustomSynchronizationContext(); try { SynchronizationContext.SetSynchronizationContext(sc); var pipe = new Pipe(); Func <Task> doRead = async() => { ReadResult result = await pipe.Reader.ReadAsync(); pipe.Reader.AdvanceTo(result.Buffer.End, result.Buffer.End); pipe.Reader.Complete(); }; // This needs to run on the current SynchronizationContext Task reading = doRead(); PipeWriter buffer = pipe.Writer; buffer.Write(Encoding.UTF8.GetBytes("Hello World")); // Don't run code on our sync context (we just want to make sure the callbacks) // are scheduled on the sync context await buffer.FlushAsync().ConfigureAwait(false); Assert.Equal(1, sc.Callbacks.Count); sc.Callbacks[0].Item1(sc.Callbacks[0].Item2); pipe.Writer.Complete(); // Don't run code on our sync context await reading.ConfigureAwait(false); } finally { SynchronizationContext.SetSynchronizationContext(previous); } }
public async Task UseSynchronizationContextFalseIgnoresSyncContextForReaderScheduler() { SynchronizationContext previous = SynchronizationContext.Current; var sc = new CustomSynchronizationContext(); try { SynchronizationContext.SetSynchronizationContext(sc); var pipe = new Pipe(new PipeOptions(useSynchronizationContext: false)); Func <Task> doRead = async() => { ReadResult result = await pipe.Reader.ReadAsync(); pipe.Reader.AdvanceTo(result.Buffer.End, result.Buffer.End); pipe.Reader.Complete(); }; // This needs to run on the current SynchronizationContext Task reading = doRead(); PipeWriter buffer = pipe.Writer; buffer.Write("Hello World" u8.ToArray()); // Don't run code on our sync context (we just want to make sure the callbacks) // are scheduled on the sync context await buffer.FlushAsync().ConfigureAwait(false); // Nothing posted to the sync context Assert.Equal(0, sc.Callbacks.Count); pipe.Writer.Complete(); // Don't run code on our sync context await reading.ConfigureAwait(false); } finally { SynchronizationContext.SetSynchronizationContext(previous); } }
public void ContextDisposable1_Test() { // arrange bool isDisposedOnContext = false; var context = new CustomSynchronizationContext(); var innerDisposable = Disposable.Create(() => isDisposedOnContext = (SynchronizationContext.Current == context)); var disp = new ContextDisposable(context, innerDisposable); // act disp.Dispose(); // just blocking until context execution completion context.Wait(); // verify Assert.IsNull(SynchronizationContext.Current); Assert.IsTrue(disp.IsDisposed); Assert.IsTrue(isDisposedOnContext); }
private static void Launch(UserCodeExceptionCatchMode exceptionMode) { EngineSetting.UserCodeExceptionCatchMode = exceptionMode; try { Elffy.Diagnostics.DevEnv.Run(); Engine.Run(); var screen = CreateScreen(); screen.Initialized += OnScreenInitialized; CustomSynchronizationContext.Install(out var syncContextReciever); screen.Activate(); while (Engine.HandleOnce()) { syncContextReciever?.DoAll(); } } finally { CustomSynchronizationContext.Restore(); Engine.Stop(); Elffy.Diagnostics.DevEnv.Stop(); } }
public async Task DefaultReaderSchedulerRunsOnSynchronizationContext() { SynchronizationContext previous = SynchronizationContext.Current; var sc = new CustomSynchronizationContext(); try { SynchronizationContext.SetSynchronizationContext(sc); var pipe = new Pipe(); Func <Task> doRead = async() => { ReadResult result = await pipe.Reader.ReadAsync(); pipe.Reader.AdvanceTo(result.Buffer.End, result.Buffer.End); pipe.Reader.Complete(); }; Task reading = doRead(); PipeWriter buffer = pipe.Writer; buffer.Write(Encoding.UTF8.GetBytes("Hello World")); await buffer.FlushAsync(); Assert.Equal(1, sc.Callbacks.Count); sc.Callbacks[0].Item1(sc.Callbacks[0].Item2); pipe.Writer.Complete(); await reading; } finally { SynchronizationContext.SetSynchronizationContext(previous); } }