public async Task Post_BackgroundWorkItem_CanProcessMoreItemsInline() { // Arrange var context = new RendererSynchronizationContext(); Thread capturedThread = null; var e1 = new ManualResetEventSlim(); var e2 = new ManualResetEventSlim(); var e3 = new ManualResetEventSlim(); var e4 = new ManualResetEventSlim(); var e5 = new ManualResetEventSlim(); var e6 = new ManualResetEventSlim(); // Force task2 to execute in the background var task1 = Task.Run(() => context.Send((_) => { e1.Set(); Assert.True(e2.Wait(Timeout), "timeout"); }, null)); Assert.True(e1.Wait(Timeout), "timeout"); var task2 = Task.Run(() => { context.Send((_) => { e3.Set(); Assert.True(e4.Wait(Timeout), "timeout"); capturedThread = Thread.CurrentThread; }, null); }); e2.Set(); await task1; Assert.True(e3.Wait(Timeout), "timeout"); // Act // // Now task2 is 'running' in the sync context. Schedule more work items - they will be // run immediately after the second item context.Post((_) => { e5.Set(); Assert.Same(Thread.CurrentThread, capturedThread); }, null); context.Post((_) => { e6.Set(); Assert.Same(Thread.CurrentThread, capturedThread); }, null); // Assert e4.Set(); await task2; Assert.True(e5.Wait(Timeout), "timeout"); Assert.True(e6.Wait(Timeout), "timeout"); }
public void Post_CapturesContext() { // Arrange var context = new RendererSynchronizationContext(); var e1 = new ManualResetEventSlim(); // CultureInfo uses the execution context. CultureInfo.CurrentCulture = new CultureInfo("en-GB"); CultureInfo capturedCulture = null; SynchronizationContext capturedContext = null; // Act context.Post(async(_) => { await Task.Yield(); capturedCulture = CultureInfo.CurrentCulture; capturedContext = SynchronizationContext.Current; e1.Set(); }, null); // Assert Assert.True(e1.Wait(Timeout), "timeout"); Assert.Same(CultureInfo.CurrentCulture, capturedCulture); Assert.Same(context, capturedContext); }
public void Post_CanRunSynchronously_WhenNotBusy_Exception() { // Arrange var context = new RendererSynchronizationContext(); // Act & Assert Assert.Throws <InvalidTimeZoneException>(() => context.Post((_) => { throw new InvalidTimeZoneException(); }, null)); }
public async Task Post_CanRunAsynchronously_CaptureExecutionContext() { // Arrange var context = new RendererSynchronizationContext(); // CultureInfo uses the execution context. CultureInfo.CurrentCulture = new CultureInfo("en-GB"); CultureInfo capturedCulture = null; SynchronizationContext capturedContext = null; var e1 = new ManualResetEventSlim(); var e2 = new ManualResetEventSlim(); var e3 = new ManualResetEventSlim(); var task = Task.Run(() => { context.Send((_) => { e1.Set(); Assert.True(e2.Wait(Timeout), "timeout"); }, null); }); Assert.True(e1.Wait(Timeout), "timeout"); // Act SynchronizationContext original = SynchronizationContext.Current; try { SynchronizationContext.SetSynchronizationContext(context); context.Post((_) => { capturedCulture = CultureInfo.CurrentCulture; capturedContext = SynchronizationContext.Current; e3.Set(); }, null); } finally { SynchronizationContext.SetSynchronizationContext(original); } // Assert Assert.False(e2.IsSet); e2.Set(); // Unblock the first item await task; Assert.True(e3.Wait(Timeout), "timeout"); Assert.Same(CultureInfo.CurrentCulture, capturedCulture); Assert.Same(context, capturedContext); }
public void Post_CanRunSynchronously_WhenNotBusy() { // Arrange var context = new RendererSynchronizationContext(); var thread = Thread.CurrentThread; Thread capturedThread = null; // Act context.Post((_) => { capturedThread = Thread.CurrentThread; }, null); // Assert Assert.Same(thread, capturedThread); }
public async Task Post_CanRunAsynchronously_WhenBusy_Exception() { // Arrange var context = new RendererSynchronizationContext(); Exception exception = null; context.UnhandledException += (sender, e) => { exception = (InvalidTimeZoneException)e.ExceptionObject; }; var e1 = new ManualResetEventSlim(); var e2 = new ManualResetEventSlim(); var task = Task.Run(() => { context.Send((_) => { e1.Set(); Assert.True(e2.Wait(Timeout), "timeout"); }, null); }); Assert.True(e1.Wait(Timeout), "timeout"); // Act context.Post((_) => { throw new InvalidTimeZoneException(); }, null); // Assert Assert.False(e2.IsSet); e2.Set(); // Unblock the first item await task; // Use another item to 'push through' the throwing one context.Send((_) => { }, null); Assert.NotNull(exception); }
public void Post_RunsAsynchronously_WhenNotBusy() { // Arrange var context = new RendererSynchronizationContext(); var thread = Thread.CurrentThread; Thread capturedThread = null; var e = new ManualResetEventSlim(); // Act context.Post((_) => { capturedThread = Thread.CurrentThread; e.Set(); }, null); // Assert Assert.True(e.Wait(Timeout), "timeout"); Assert.NotSame(thread, capturedThread); }
public async Task Post_CanRunAsynchronously_WhenBusy() { // Arrange var context = new RendererSynchronizationContext(); var thread = Thread.CurrentThread; Thread capturedThread = null; var e1 = new ManualResetEventSlim(); var e2 = new ManualResetEventSlim(); var e3 = new ManualResetEventSlim(); var task = Task.Run(() => { context.Send((_) => { e1.Set(); Assert.True(e2.Wait(Timeout), "timeout"); }, null); }); Assert.True(e1.Wait(Timeout), "timeout"); // Act context.Post((_) => { capturedThread = Thread.CurrentThread; e3.Set(); }, null); // Assert Assert.False(e2.IsSet); e2.Set(); // Unblock the first item await task; Assert.True(e3.Wait(Timeout), "timeout"); Assert.NotSame(thread, capturedThread); }
public void Post_RunsAsynchronously_WhenNotBusy_Exception() { // Arrange var context = new RendererSynchronizationContext(); Exception exception = null; context.UnhandledException += (sender, e) => { exception = (InvalidTimeZoneException)e.ExceptionObject; }; // Act context.Post((_) => { throw new InvalidTimeZoneException(); }, null); // Assert // // Use another item to 'push through' the throwing one context.Send((_) => { }, null); Assert.NotNull(exception); }