public static void RunAsyncTaskAwaiterAdditionalBehaviorsTests() { // Test that base SynchronizationContext is treated the same as no SynchronizationContext for awaits { var quwi = new QUWITaskScheduler(); SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); RunWithSchedulerAsCurrent(quwi, delegate { ManualResetEventSlim mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource <object>(); int result = 1; var awaiter = ((Task)tcs.Task).GetAwaiter(); Assert.False(awaiter.IsCompleted, " > FAILURE. Awaiter on non-completed task should not be IsCompleted"); Assert.True(SynchronizationContext.Current != null, " > FAILURE. Expected a current SyncCtx but found null"); awaiter.OnCompleted(() => { Assert.True(TaskScheduler.Current == quwi, " > FAILURE. Continuation should be running in task scheduler."); Assert.True(SynchronizationContext.Current == null, " > FAILURE. Expected no current SyncCtx but found " + SynchronizationContext.Current); result = 2; mres.Set(); }); Assert.True(result == 1, " > FAILURE. Await continuation should not run until task completes."); Task.Run(delegate { tcs.SetResult(null); }); mres.Wait(); awaiter.GetResult(); Assert.True(result == 2, " > FAILURE. Await continuation should have completed."); }); SynchronizationContext.SetSynchronizationContext(null); } }
public static async Task AsyncMethod_Yields_ReturnsToCorrectTaskScheduler() { QUWITaskScheduler ts = new QUWITaskScheduler(); Assert.NotSame(ts, TaskScheduler.Current); await Task.Factory.StartNew(async delegate { Assert.Same(ts, TaskScheduler.Current); await Task.Yield(); Assert.Same(ts, TaskScheduler.Current); }, CancellationToken.None, TaskCreationOptions.None, ts).Unwrap(); Assert.NotSame(ts, TaskScheduler.Current); }
public static void OnCompleted_CompletesInAnotherTaskScheduler(bool generic, bool? continueOnCapturedContext) { SynchronizationContext origCtx = SynchronizationContext.Current; try { SynchronizationContext.SetSynchronizationContext(null); // get off xunit's SynchronizationContext to avoid interactions with await var quwi = new QUWITaskScheduler(); RunWithSchedulerAsCurrent(quwi, delegate { Assert.True(TaskScheduler.Current == quwi, "Expected to be on target scheduler"); // Create the not completed task and get its awaiter var mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource<object>(); // Hook up the callback bool ranOnScheduler = false; Action callback = () => { ranOnScheduler = (TaskScheduler.Current == quwi); mres.Set(); }; if (generic) { if (continueOnCapturedContext.HasValue) tcs.Task.ConfigureAwait(continueOnCapturedContext.Value).GetAwaiter().OnCompleted(callback); else tcs.Task.GetAwaiter().OnCompleted(callback); } else { if (continueOnCapturedContext.HasValue) ((Task)tcs.Task).ConfigureAwait(continueOnCapturedContext.Value).GetAwaiter().OnCompleted(callback); else ((Task)tcs.Task).GetAwaiter().OnCompleted(callback); } Assert.False(mres.IsSet, "Callback should not yet have run."); // Complete the task in another scheduler and wait for the callback to run Task.Run(delegate { tcs.SetResult(null); }); mres.Wait(); // Validate the callback ran on the right scheduler bool shouldHaveRunOnScheduler = !continueOnCapturedContext.HasValue || continueOnCapturedContext.Value; Assert.Equal(shouldHaveRunOnScheduler, ranOnScheduler); }); } finally { SynchronizationContext.SetSynchronizationContext(origCtx); } }
public static void BaseSynchronizationContext_SameAsNoSynchronizationContext() { var quwi = new QUWITaskScheduler(); SynchronizationContext origCtx = SynchronizationContext.Current; try { SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); RunWithSchedulerAsCurrent(quwi, delegate { ManualResetEventSlim mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource <object>(); var awaiter = ((Task)tcs.Task).GetAwaiter(); bool ranOnScheduler = false; bool ranWithoutSyncCtx = false; awaiter.OnCompleted(() => { ranOnScheduler = (TaskScheduler.Current == quwi); ranWithoutSyncCtx = SynchronizationContext.Current == null; mres.Set(); }); Assert.False(mres.IsSet, "Callback should not yet have run."); Task.Run(delegate { tcs.SetResult(null); }); mres.Wait(); Assert.True(ranOnScheduler, "Should have run on scheduler"); Assert.True(ranWithoutSyncCtx, "Should have run with a null sync ctx"); }); } finally { SynchronizationContext.SetSynchronizationContext(origCtx); } }
public static void BaseSynchronizationContext_SameAsNoSynchronizationContext() { var quwi = new QUWITaskScheduler(); SynchronizationContext origCtx = SynchronizationContext.Current; try { SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); RunWithSchedulerAsCurrent(quwi, delegate { ManualResetEventSlim mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource<object>(); var awaiter = ((Task)tcs.Task).GetAwaiter(); bool ranOnScheduler = false; bool ranWithoutSyncCtx = false; awaiter.OnCompleted(() => { ranOnScheduler = (TaskScheduler.Current == quwi); ranWithoutSyncCtx = SynchronizationContext.Current == null; mres.Set(); }); Assert.False(mres.IsSet, "Callback should not yet have run."); Task.Run(delegate { tcs.SetResult(null); }); mres.Wait(); Assert.True(ranOnScheduler, "Should have run on scheduler"); Assert.True(ranWithoutSyncCtx, "Should have run with a null sync ctx"); }); } finally { SynchronizationContext.SetSynchronizationContext(origCtx); } }
public static void OnCompleted_CompletesInAnotherTaskScheduler(bool generic, bool?continueOnCapturedContext) { SynchronizationContext origCtx = SynchronizationContext.Current; try { SynchronizationContext.SetSynchronizationContext(null); // get off xunit's SynchronizationContext to avoid interactions with await var quwi = new QUWITaskScheduler(); RunWithSchedulerAsCurrent(quwi, delegate { Assert.True(TaskScheduler.Current == quwi, "Expected to be on target scheduler"); // Create the not completed task and get its awaiter var mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource <object>(); // Hook up the callback bool ranOnScheduler = false; Action callback = () => { ranOnScheduler = (TaskScheduler.Current == quwi); mres.Set(); }; if (generic) { if (continueOnCapturedContext.HasValue) { tcs.Task.ConfigureAwait(continueOnCapturedContext.Value).GetAwaiter().OnCompleted(callback); } else { tcs.Task.GetAwaiter().OnCompleted(callback); } } else { if (continueOnCapturedContext.HasValue) { ((Task)tcs.Task).ConfigureAwait(continueOnCapturedContext.Value).GetAwaiter().OnCompleted(callback); } else { ((Task)tcs.Task).GetAwaiter().OnCompleted(callback); } } Assert.False(mres.IsSet, "Callback should not yet have run."); // Complete the task in another scheduler and wait for the callback to run Task.Run(delegate { tcs.SetResult(null); }); mres.Wait(); // Validate the callback ran on the right scheduler bool shouldHaveRunOnScheduler = !continueOnCapturedContext.HasValue || continueOnCapturedContext.Value; Assert.Equal(shouldHaveRunOnScheduler, ranOnScheduler); }); } finally { SynchronizationContext.SetSynchronizationContext(origCtx); } }
public static void RunAsyncTaskAwaiterAdditionalBehaviorsTests() { // Test that base SynchronizationContext is treated the same as no SynchronizationContext for awaits { var quwi = new QUWITaskScheduler(); SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); RunWithSchedulerAsCurrent(quwi, delegate { ManualResetEventSlim mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource<object>(); int result = 1; var awaiter = ((Task)tcs.Task).GetAwaiter(); Assert.False(awaiter.IsCompleted, " > FAILURE. Awaiter on non-completed task should not be IsCompleted"); Assert.True(SynchronizationContext.Current != null, " > FAILURE. Expected a current SyncCtx but found null"); awaiter.OnCompleted(() => { Assert.True(TaskScheduler.Current == quwi, " > FAILURE. Continuation should be running in task scheduler."); Assert.True(SynchronizationContext.Current == null, " > FAILURE. Expected no current SyncCtx but found " + SynchronizationContext.Current); result = 2; mres.Set(); }); Assert.True(result == 1, " > FAILURE. Await continuation should not run until task completes."); Task.Run(delegate { tcs.SetResult(null); }); mres.Wait(); awaiter.GetResult(); Assert.True(result == 2, " > FAILURE. Await continuation should have completed."); }); SynchronizationContext.SetSynchronizationContext(null); } }
public static void RunAsyncTaskAwaiterTests() { var completed = new TaskCompletionSource<string>(); Task task = completed.Task; Task<string> taskOfString = completed.Task; completed.SetResult("42"); { // IsCompleted/OnCompleted on a non-completed Task with SyncContext and completes the task in another context var vccsc = new ValidateCorrectContextSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(vccsc); ManualResetEventSlim mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource<object>(); int result = 1; var awaiter = ((Task)tcs.Task).GetAwaiter(); Assert.False(awaiter.IsCompleted, " > FAILURE. Awaiter on non-completed task should not be IsCompleted"); awaiter.OnCompleted(() => { Assert.True(ValidateCorrectContextSynchronizationContext.IsPostedInContext, " > FAILURE. Continuation should be running in captured sync context."); result = 2; mres.Set(); }); Assert.True(result == 1, " > FAILURE. Await continuation should not run until task completes."); Task.Run(delegate { tcs.SetResult(null); }); mres.Wait(); awaiter.GetResult(); Assert.True(result == 2, " > FAILURE. Await continuation should have completed."); Assert.True(vccsc.PostCount == 1, " > FAILURE. Await continuation should have posted to the target context."); SynchronizationContext.SetSynchronizationContext(null); } { // IsCompleted/OnCompleted on a non-completed Task with TaskScheduler and completes the task in another context var quwi = new QUWITaskScheduler(); RunWithSchedulerAsCurrent(quwi, delegate { ManualResetEventSlim mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource<object>(); int result = 1; var awaiter = ((Task)tcs.Task).GetAwaiter(); Assert.False(awaiter.IsCompleted, " > FAILURE. Awaiter on non-completed task should not be IsCompleted"); awaiter.OnCompleted(() => { Assert.True(TaskScheduler.Current == quwi, " > FAILURE. Continuation should be running in task scheduler."); result = 2; mres.Set(); }); Assert.True(result == 1, " > FAILURE. Await continuation should not run until task completes."); Task.Run(delegate { tcs.SetResult(null); }); mres.Wait(); awaiter.GetResult(); Assert.True(result == 2, " > FAILURE. Await continuation should have completed."); }); } { // Configured IsCompleted/OnCompleted on a non-completed Task with SyncContext for (int iter = 0; iter < 2; iter++) { Task.Factory.StartNew(() => { bool continueOnCapturedContext = iter == 0; SynchronizationContext.SetSynchronizationContext(new ValidateCorrectContextSynchronizationContext()); ManualResetEventSlim mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource<object>(); int result = 1; var awaiter = ((Task)tcs.Task).ConfigureAwait(continueOnCapturedContext).GetAwaiter(); Assert.False(awaiter.IsCompleted, " > FAILURE. Configured awaiter on non-completed task should not be IsCompleted"); awaiter.OnCompleted(() => { Assert.True(ValidateCorrectContextSynchronizationContext.IsPostedInContext == continueOnCapturedContext, " > FAILURE. Continuation should have been posted to context iff continueOnCapturedContext == true."); // // Assert.True(Environment.StackTrace.Contains("SetResult") != continueOnCapturedContext, // " > FAILURE. Continuation should have been executed synchronously iff continueOnCapturedContext == false."); result = 2; mres.Set(); }); Assert.True(result == 1, " > FAILURE. Await continuation should not have run before task completed."); Task.Factory.StartNew(() => tcs.SetResult(null)); mres.Wait(); awaiter.GetResult(); Assert.True(result == 2, " > FAILURE. Await continuation should now have completed."); SynchronizationContext.SetSynchronizationContext(null); }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Wait(); } } { // IsCompleted/OnCompleted on a non-completed Task<TResult> with SyncContext and completes the task in another context var vccsc = new ValidateCorrectContextSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(vccsc); var mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource<object>(); int result = 1; var awaiter = ((Task<object>)tcs.Task).GetAwaiter(); Assert.False(awaiter.IsCompleted, " > FAILURE. Awaiter on non-completed Task<TResult> should not be IsCompleted"); awaiter.OnCompleted(() => { Assert.True(ValidateCorrectContextSynchronizationContext.IsPostedInContext, " > FAILURE. Await continuation should have posted to target context"); result = 2; mres.Set(); }); Assert.True(result == 1, " > FAILURE. Await continuation should not have run before task completed."); Task.Run(delegate { tcs.SetResult(null); }); mres.Wait(); awaiter.GetResult(); Assert.True(result == 2, " > FAILURE. Await continuation should now have completed."); Assert.True(vccsc.PostCount == 1, " > FAILURE. Await continuation should have posted to the target context"); SynchronizationContext.SetSynchronizationContext(null); } { // Configured IsCompleted/OnCompleted on a non-completed Task<TResult> with SyncContext for (int iter = 0; iter < 2; iter++) { Task.Factory.StartNew(() => { bool continueOnCapturedContext = iter == 0; SynchronizationContext.SetSynchronizationContext(new ValidateCorrectContextSynchronizationContext()); var mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource<object>(); int result = 1; var awaiter = tcs.Task.ConfigureAwait(continueOnCapturedContext).GetAwaiter(); Assert.False(awaiter.IsCompleted, " > FAILURE. Configured awaiter on non-completed Task<TResult> should not be IsCompleted"); awaiter.OnCompleted(() => { Assert.True( ValidateCorrectContextSynchronizationContext.IsPostedInContext == continueOnCapturedContext, " > FAILURE. Await continuation should have posted to target context iff continueOnCapturedContext == true"); // Assert.True( // Environment.StackTrace.Contains("SetResult") != continueOnCapturedContext, // " > FAILURE. Await continuation should have executed inline iff continueOnCapturedContext == false"); result = 2; mres.Set(); }); Assert.True(result == 1, " > FAILURE. Await continuation should not have run before task completed."); Task.Factory.StartNew(() => tcs.SetResult(null)); mres.Wait(); awaiter.GetResult(); Assert.True(result == 2, " > FAILURE. Await continuation should now have completed."); SynchronizationContext.SetSynchronizationContext(null); }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Wait(); } } { // Validate successful GetResult task.GetAwaiter().GetResult(); task.ConfigureAwait(false).GetAwaiter().GetResult(); task.ConfigureAwait(true).GetAwaiter().GetResult(); Assert.Equal(taskOfString.GetAwaiter().GetResult(), "42"); Assert.Equal(taskOfString.ConfigureAwait(false).GetAwaiter().GetResult(), "42"); Assert.Equal(taskOfString.ConfigureAwait(true).GetAwaiter().GetResult(), "42"); } { // Validate GetResult blocks until completion var tcs = new TaskCompletionSource<bool>(); // Kick off tasks that should all block var t1 = Task.Factory.StartNew(() => tcs.Task.GetAwaiter().GetResult()); var t2 = Task.Factory.StartNew(() => ((Task)tcs.Task).GetAwaiter().GetResult()); var t3 = Task.Factory.StartNew(() => tcs.Task.ConfigureAwait(false).GetAwaiter().GetResult()); var t4 = Task.Factory.StartNew(() => ((Task)tcs.Task).ConfigureAwait(false).GetAwaiter().GetResult()); var allTasks = new Task[] { t1, t2, t3, t4 }; // Wait with timeout should return false bool waitCompleted; try { waitCompleted = Task.WaitAll(allTasks, 4000); Assert.False(waitCompleted, " > Expected tasks to not be completed"); } catch (Exception exc) { Assert.True(false, string.Format(" > Did not expect an exception: " + exc)); } // Now complete the tasks tcs.SetResult(true); // All tasks should complete successfully waitCompleted = Task.WaitAll(allTasks, 4000); Assert.True(waitCompleted, "After completion, excepted all GetResult calls to completed successfully"); foreach (var taskToCheck in allTasks) { Assert.True(taskToCheck.Status == TaskStatus.RanToCompletion, "Task was not run to completion. Excepted all GetResult calls to completed successfully"); } } }
public static void RunAsyncTaskAwaiterTests() { var completed = new TaskCompletionSource <string>(); Task task = completed.Task; Task <string> taskOfString = completed.Task; completed.SetResult("42"); { // IsCompleted/OnCompleted on a non-completed Task with SyncContext and completes the task in another context var vccsc = new ValidateCorrectContextSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(vccsc); ManualResetEventSlim mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource <object>(); int result = 1; var awaiter = ((Task)tcs.Task).GetAwaiter(); Assert.False(awaiter.IsCompleted, " > FAILURE. Awaiter on non-completed task should not be IsCompleted"); awaiter.OnCompleted(() => { Assert.True(ValidateCorrectContextSynchronizationContext.IsPostedInContext, " > FAILURE. Continuation should be running in captured sync context."); result = 2; mres.Set(); }); Assert.True(result == 1, " > FAILURE. Await continuation should not run until task completes."); Task.Run(delegate { tcs.SetResult(null); }); mres.Wait(); awaiter.GetResult(); Assert.True(result == 2, " > FAILURE. Await continuation should have completed."); Assert.True(vccsc.PostCount == 1, " > FAILURE. Await continuation should have posted to the target context."); SynchronizationContext.SetSynchronizationContext(null); } { // IsCompleted/OnCompleted on a non-completed Task with TaskScheduler and completes the task in another context var quwi = new QUWITaskScheduler(); RunWithSchedulerAsCurrent(quwi, delegate { ManualResetEventSlim mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource <object>(); int result = 1; var awaiter = ((Task)tcs.Task).GetAwaiter(); Assert.False(awaiter.IsCompleted, " > FAILURE. Awaiter on non-completed task should not be IsCompleted"); awaiter.OnCompleted(() => { Assert.True(TaskScheduler.Current == quwi, " > FAILURE. Continuation should be running in task scheduler."); result = 2; mres.Set(); }); Assert.True(result == 1, " > FAILURE. Await continuation should not run until task completes."); Task.Run(delegate { tcs.SetResult(null); }); mres.Wait(); awaiter.GetResult(); Assert.True(result == 2, " > FAILURE. Await continuation should have completed."); }); } { // Configured IsCompleted/OnCompleted on a non-completed Task with SyncContext for (int iter = 0; iter < 2; iter++) { Task.Factory.StartNew(() => { bool continueOnCapturedContext = iter == 0; SynchronizationContext.SetSynchronizationContext(new ValidateCorrectContextSynchronizationContext()); ManualResetEventSlim mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource <object>(); int result = 1; var awaiter = ((Task)tcs.Task).ConfigureAwait(continueOnCapturedContext).GetAwaiter(); Assert.False(awaiter.IsCompleted, " > FAILURE. Configured awaiter on non-completed task should not be IsCompleted"); awaiter.OnCompleted(() => { Assert.True(ValidateCorrectContextSynchronizationContext.IsPostedInContext == continueOnCapturedContext, " > FAILURE. Continuation should have been posted to context iff continueOnCapturedContext == true."); // // Assert.True(Environment.StackTrace.Contains("SetResult") != continueOnCapturedContext, // " > FAILURE. Continuation should have been executed synchronously iff continueOnCapturedContext == false."); result = 2; mres.Set(); }); Assert.True(result == 1, " > FAILURE. Await continuation should not have run before task completed."); Task.Factory.StartNew(() => tcs.SetResult(null)); mres.Wait(); awaiter.GetResult(); Assert.True(result == 2, " > FAILURE. Await continuation should now have completed."); SynchronizationContext.SetSynchronizationContext(null); }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Wait(); } } { // IsCompleted/OnCompleted on a non-completed Task<TResult> with SyncContext and completes the task in another context var vccsc = new ValidateCorrectContextSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(vccsc); var mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource <object>(); int result = 1; var awaiter = ((Task <object>)tcs.Task).GetAwaiter(); Assert.False(awaiter.IsCompleted, " > FAILURE. Awaiter on non-completed Task<TResult> should not be IsCompleted"); awaiter.OnCompleted(() => { Assert.True(ValidateCorrectContextSynchronizationContext.IsPostedInContext, " > FAILURE. Await continuation should have posted to target context"); result = 2; mres.Set(); }); Assert.True(result == 1, " > FAILURE. Await continuation should not have run before task completed."); Task.Run(delegate { tcs.SetResult(null); }); mres.Wait(); awaiter.GetResult(); Assert.True(result == 2, " > FAILURE. Await continuation should now have completed."); Assert.True(vccsc.PostCount == 1, " > FAILURE. Await continuation should have posted to the target context"); SynchronizationContext.SetSynchronizationContext(null); } { // Configured IsCompleted/OnCompleted on a non-completed Task<TResult> with SyncContext for (int iter = 0; iter < 2; iter++) { Task.Factory.StartNew(() => { bool continueOnCapturedContext = iter == 0; SynchronizationContext.SetSynchronizationContext(new ValidateCorrectContextSynchronizationContext()); var mres = new ManualResetEventSlim(); var tcs = new TaskCompletionSource <object>(); int result = 1; var awaiter = tcs.Task.ConfigureAwait(continueOnCapturedContext).GetAwaiter(); Assert.False(awaiter.IsCompleted, " > FAILURE. Configured awaiter on non-completed Task<TResult> should not be IsCompleted"); awaiter.OnCompleted(() => { Assert.True( ValidateCorrectContextSynchronizationContext.IsPostedInContext == continueOnCapturedContext, " > FAILURE. Await continuation should have posted to target context iff continueOnCapturedContext == true"); // Assert.True( // Environment.StackTrace.Contains("SetResult") != continueOnCapturedContext, // " > FAILURE. Await continuation should have executed inline iff continueOnCapturedContext == false"); result = 2; mres.Set(); }); Assert.True(result == 1, " > FAILURE. Await continuation should not have run before task completed."); Task.Factory.StartNew(() => tcs.SetResult(null)); mres.Wait(); awaiter.GetResult(); Assert.True(result == 2, " > FAILURE. Await continuation should now have completed."); SynchronizationContext.SetSynchronizationContext(null); }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Wait(); } } { // Validate successful GetResult task.GetAwaiter().GetResult(); task.ConfigureAwait(false).GetAwaiter().GetResult(); task.ConfigureAwait(true).GetAwaiter().GetResult(); Assert.Equal(taskOfString.GetAwaiter().GetResult(), "42"); Assert.Equal(taskOfString.ConfigureAwait(false).GetAwaiter().GetResult(), "42"); Assert.Equal(taskOfString.ConfigureAwait(true).GetAwaiter().GetResult(), "42"); } { // Validate GetResult blocks until completion var tcs = new TaskCompletionSource <bool>(); // Kick off tasks that should all block var t1 = Task.Factory.StartNew(() => tcs.Task.GetAwaiter().GetResult()); var t2 = Task.Factory.StartNew(() => ((Task)tcs.Task).GetAwaiter().GetResult()); var t3 = Task.Factory.StartNew(() => tcs.Task.ConfigureAwait(false).GetAwaiter().GetResult()); var t4 = Task.Factory.StartNew(() => ((Task)tcs.Task).ConfigureAwait(false).GetAwaiter().GetResult()); var allTasks = new Task[] { t1, t2, t3, t4 }; // Wait with timeout should return false bool waitCompleted; try { waitCompleted = Task.WaitAll(allTasks, 4000); Assert.False(waitCompleted, " > Expected tasks to not be completed"); } catch (Exception exc) { Assert.True(false, string.Format(" > Did not expect an exception: " + exc)); } // Now complete the tasks tcs.SetResult(true); // All tasks should complete successfully waitCompleted = Task.WaitAll(allTasks, 4000); Assert.True(waitCompleted, "After completion, excepted all GetResult calls to completed successfully"); foreach (var taskToCheck in allTasks) { Assert.True(taskToCheck.Status == TaskStatus.RanToCompletion, "Task was not run to completion. Excepted all GetResult calls to completed successfully"); } } }