public static string pingAllChildren(string myIp) { object locker = new object(); string res = string.Empty; for (int i = 1; i < 5; i++) { int j = i; Task.Run(async () => { string ip = myIp.Remove(myIp.LastIndexOf('.'), myIp.Length - myIp.LastIndexOf('.')) + $".{j + 10}"; IPStatus t = await pingAsync($"{ip}"); lock (locker) { res += $"{ip} : {t.ToString()}\n"; } }).Wait(); //string ip = myIp.Remove(myIp.LastIndexOf('.'), myIp.Length - myIp.LastIndexOf('.')) + $".{j + 10}"; //ThreadPool.QueueUserWorkItem(pingAsync(ip)); } return res; } 

if Wait() removed, then return an empty result. And so no asynchrony.

How do I wait for all threads to complete to return the result normally?

  • one
    You collect all your tasks into an array and wait for Task.WaitAll (array) - adrug
  • And it is better to use different res, and then collect the result from the task and zadzhoynit - adrug
  • @adrug Chet provtykal this moment, thank you - Vitaly Shebanits
  • Throw out completely Task.Run . The pingAsync method returns a task, here these tasks and put in an array (sheet). Then wait for them to complete Task.Wait . As a result, all pings are performed in parallel. This does not create a single excess flow. It does not need a lock: discard lock . - Alexander Petrov
  • @Alexander Petrov why is it not necessary to block? If two threads simultaneously write to a variable, then what happens? - Vitaliy Shebanits September

3 answers 3

In my opinion it would be better to do this:

 public static string pingAllChildren(string myIp) { var pings = Enumerable.Range(1, 4).Select(i => myIp.Remove(myIp.LastIndexOf('.'), myIp.Length - myIp.LastIndexOf('.')) + $".{i + 10}") .Select(ip => new { ip, task = pingAsync(ip) }).ToList(); Task.WaitAll(pings.Select(p => p.task).ToArray()); return string.Join(Environment.NewLine, pings.Select(p => $"{p.ip} : {p.task.Result}")); } 

First, we create the IPs we need and run the ping task. We place this in an anonymous object so that later we do not lose the pinged IP. Then all the tasks from the array are string.Join and only after that through string.Join we create a formatted result.

  • why not make the whole function asynchronous? - tym32167
  • Then where the challenge will have to be corrected more) - adrug
  • what the author is doing now, if you look at the accepted answer :) - tym32167
 await Task.Run(async () => { // }); 
  • Thank you very much - Vitaly Shebanits September
  • four
    It actually changes nothing. As before, all calls (pings) will be executed sequentially. - Alexander Petrov
  • Yes, I did not understand the problem. Added another answer. - vusaldev

I'm sorry, I misunderstood the task. Your problem can be solved with the help of callbacks that are executed after the completion of the task.

  public static string pingAllChildren(string myIp) { List<Task> taskList = new List<Task>(); object locker = new object(); string res = string.Empty; Action<Task<string>> act = (Task<string> a) => { res += a.Result; }; for (int i = 1; i < 5; i++) { int j = i; Task fooWrappedInTask = Task.Run( async () => { string res1 = null; string ip = myIp.Remove(myIp.LastIndexOf('.'), myIp.Length - myIp.LastIndexOf('.')) + $".{j + 10}"; IPStatus t = await pingAsync($"{ip}"); lock (locker) { res1 += $"{ip} : {t.ToString()}\n"; } return res1; }).ContinueWith(act); taskList.Add(fooWrappedInTask); } Task.WaitAll(taskList.ToArray()); return res; } 
  • If you minus it, then at least write for what, make SO and commentators better. My answer is correct, it does not affect the external code, and at the same time gives the beginner to figure out what's what, since it is not a porridge from LINQ. - vusaldev