/// <summary> /// Does a parallel ForEach around a non-blocking method with async/await /// </summary> /// <remarks>Even though Parallel.ForEach is being used with the async/await operators, it's not doing what /// you expect; it's still not actually awaiting the tasks on the current thread so the Console.WriteLine /// is executing much earlier than you would expect, before any of the method calls have completed. /// NB even though Parallel.ForEach uses async/await in its lambda, it is not itself async so we /// do not need to mark this test method as async</remarks> private static Task ParallelForEachDelayLoopWithAsyncTests() { var sw = BeginExample("ParallelForEachDelayLoopWithAsyncTests starting..."); var array = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; var sut = new NonBlockingMethod(); Parallel.ForEach(array, async(i, state) => await sut.StartIteration(i, DelayDurationOne, "ParallelForEachDelayLoopWithAsyncTests")); sw.Stop(); Console.WriteLine($"Duration of Parallel.ForEach delay iteration loop for {array.Length} iterations delay for {DelayDurationOne} ms was {sw.ElapsedMilliseconds} ms"); return(Task.CompletedTask); }
/// <summary> /// Loops around a non-blocking method asynchronously but with no parallelism /// </summary> private static async Task DelayLoopTests() { var sw = BeginExample("DelayLoopTests starting..."); var sut = new NonBlockingMethod(); for (var i = 0; i < IterationCount; i++) { await sut.StartIteration(i, DelayDurationOne, "One"); } sw.Stop(); Console.WriteLine($"Duration of async delay iteration loop for {IterationCount} iterations delay for {DelayDurationOne} ms was {sw.ElapsedMilliseconds} ms"); }
/// <summary> /// Kicks off a number or tasks but instead of awaiting them it adds the tasks to a <see cref="List{Task}"/> /// and then does a Task.WhenAll on that list. /// </summary> /// <remarks>Now the Console.WriteLine executes when we expect it to, after all tasks have completed. Those /// tasks have been run in parallel though, since we weren't awaiting any individual task, just waiting /// for them all to have completed.</remarks> private static async Task TaskWhenAllDelayLoopTests() { var sw = BeginExample("TaskWhenAllDelayLoopTests starting..."); var sut = new NonBlockingMethod(); var taskList = new List <Task>(); for (var i = 1; i <= IterationCount; i++) { taskList.Add(sut.StartIteration(i, DelayDurationOne, "TaskWhenAllDelayLoopTests")); } await Task.WhenAll(taskList.ToArray()); sw.Stop(); Console.WriteLine($"Duration of Task.WhenAll delay iteration loop for {IterationCount} iterations delay for {DelayDurationOne} ms was {sw.ElapsedMilliseconds} ms"); }
/// <summary> /// Does a parallel ForEach around a non-blocking method with async/await AND attaches the tasks to the parent /// </summary> /// <remarks>Even though Parallel.ForEach is being used with the async/await operators and attaching tasks /// to the parent thread, it's still not doing what you expect; the Console.WriteLine /// is still executing much earlier than you would expect, before any of the method calls have completed. /// This may be a badly written test; I *THINK* what's happening here is that the Task.Factory.StartNew /// creates a single new task (on a new thread) that does have the parent set correctly; however that /// thread then runs the Parallel.ForEach which kicks off a bunch of new tasks, each on their own thread, /// which aren't connected to the parent as you'd hope.</remarks> private static async Task ParallelForEachDelayLoopWithAsyncAttachedTests() { var sw = BeginExample("ParallelForEachDelayLoopWithAsyncAttachedTests starting..."); var array = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; var sut = new NonBlockingMethod(); await Task.Factory.StartNew(() => { Parallel.ForEach(array, async(i, state) => await sut.StartIteration(i, DelayDurationOne, "ParallelForEachDelayLoopWithAsyncAttachedTests")); }, TaskCreationOptions.AttachedToParent); sw.Stop(); Console.WriteLine($"Duration of attached Parallel.ForEach delay iteration loop for {array.Length} iterations delay for {DelayDurationOne} ms was {sw.ElapsedMilliseconds} ms"); }
/// <summary> /// Make sure to put a breakpoint in the NonBlockingMethod.StartIteration method somewhere /// within the extraIterativeDelay logic /// </summary> /// <remarks>Can use this to demo the threads, tasks and Parallel Watch windows, freezing threads/tasks, /// switching between threads/tasks etc.</remarks> private static async Task DemoThreadDebugging() { BeginExample("DemoThreadDebugging starting..."); var count = 5; var sut = new NonBlockingMethod(); var taskList = new List <Task>(); for (int i = 1; i <= count; i++) { taskList.Add(sut.StartIteration(i, DelayDurationOne, "DemoThreadDebugging", true)); } await Task.WhenAll(taskList.ToArray()); Console.WriteLine($"DemoThreadDebugging complete"); }