Async is waiting and parallel

I am a bit confused about how async / await can work as parallel, so I made a test code here: I am trying to submit 6 tasks simulated by a list. each of these tasks will perform 3 more subtasks.

you can copy / paste for testing

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { //job simulation Func<int, string, Tuple<int, string>> tc = Tuple.Create; var input = new List<Tuple<int, string>>{ tc( 6000, "task 1" ), tc( 5000, "task 2" ), tc( 1000, "task 3" ), tc( 1000, "task 4" ), tc( 1000, "task 5" ), tc( 1000, "task 6" ) }; List<Tuple<int, string>> JobsList = new List<Tuple<int, string>>(input); //paralelism atempt List<Task> TaskLauncher = new List<Task>(); Parallel.ForEach<Tuple<int, string>>(JobsList, item => JobDispatcher(item.Item1, item.Item2)); Console.ReadLine(); } public static async Task JobDispatcher(int time , string query) { List<Task> TList = new List<Task>(); Task<string> T1 = SubTask1(time, query); Task<string> T2 = SubTask2(time, query); Task<string> T3 = SubTask3(time, query); TList.Add(T1); TList.Add(T2); TList.Add(T3); Console.WriteLine("{0} Launched ", query); await Task.WhenAll(TList.ToArray()); Console.WriteLine(T1.Result); Console.WriteLine(T2.Result); Console.WriteLine(T3.Result); } public static async Task<string> SubTask1(int time, string query) { //somework Thread.Sleep(time); return query + "Finshed SubTask1"; } public static async Task<string> SubTask2(int time, string query) { //somework Thread.Sleep(time); return query + "Finshed SubTask2"; } public static async Task<string> SubTask3(int time, string query) { //somework Thread.Sleep(time); return query + "Finshed SubTask3"; } } } 

Ideally, at startup, I should read:

 task 1 launched task 2 launched task 3 launched task 4 launched task 5 launched task 6 launched 

then at this moment all tasks start 6 * 3 = 18 threads at the same time but not what is happening here seems to be synchronizing.

Result

as follows:

what is an easy way to write something that can run a task and a subtask as 18 parralle threads with async / await?

+5
source share
1 answer

Try this sample code. Note that it completes after about 6 seconds, which indicates that all tasks are performed asynchronously:

 using System; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static void Main() { // ThreadPool throttling may cause the speed with which // the threads are launched to be throttled. // You can avoid that by uncommenting the following line, // but that is considered bad form: // ThreadPool.SetMinThreads(20, 20); var sw = Stopwatch.StartNew(); Console.WriteLine("Waiting for all tasks to complete"); RunWorkers().Wait(); Console.WriteLine("All tasks completed in " + sw.Elapsed); } public static async Task RunWorkers() { await Task.WhenAll( JobDispatcher(6000, "task 1"), JobDispatcher(5000, "task 2"), JobDispatcher(4000, "task 3"), JobDispatcher(3000, "task 4"), JobDispatcher(2000, "task 5"), JobDispatcher(1000, "task 6") ); } public static async Task JobDispatcher(int time, string query) { var results = await Task.WhenAll( worker(time, query + ": Subtask 1"), worker(time, query + ": Subtask 2"), worker(time, query + ": Subtask 3") ); Console.WriteLine(string.Join("\n", results)); } static async Task<string> worker(int time, string query) { return await Task.Run(() => { Console.WriteLine("Starting worker " + query); Thread.Sleep(time); Console.WriteLine("Completed worker " + query); return query + ": " + time + ", thread id: " + Thread.CurrentThread.ManagedThreadId; }); } } } 

Here's how you could use an array of tasks in RunWorkers() :

 public static async Task RunWorkers() { Task[] tasks = new Task[6]; for (int i = 0; i < 6; ++i) tasks[i] = JobDispatcher(1000 + i*1000, "task " + i); await Task.WhenAll(tasks); } 
+5
source

Source: https://habr.com/ru/post/1241974/


All Articles