Task.WaitAll - not waiting?

I am trying to find my task around Task.WaitAll (..) in a parallel task library.

I run the test using the following code to try to simulate two tasks that will run longer (10 seconds) than the specified amount of time to wait (10, and one less (3 seconds) than the specified amount of time out. is 5 seconds. The code I use is the following:

Task<int>[] tasks = new Task<int>[] { Task.Factory.StartNew<int>(()=> { Thread.Sleep(10000); return 1; }), Task.Factory.StartNew<int>(()=> { Thread.Sleep(3000); return 2; }) }; TimeSpan timeSpan = new TimeSpan(0, 0, 5); Task.WaitAll(tasks,timeSpan); int[] results = new int[tasks.Length]; for(int i = 0; i < tasks.Length;i++) { Console.WriteLine(tasks[i].Result); } 

As for timeSpan, I also tried directly passing 5000 instead of the timeSpan variable, but it does not work. I get the following output:

 1 2 

I would expect to get only the following result, because the other thread takes longer than the expected wait time.

 1 

Do I really not understand this or did this test wrong?

+4
source share
3 answers

Do not use Thread.Sleep in tasks. The Task Scheduler does not guarantee one thread for each task, and sleep can affect other tasks (see Task ignores Thread.Sleep ). Use Task.Delay () instead .

+3
source

While Task.Delay is what you would normally like to use instead (so you don’t lose thread during sleep), your problem is not really related to this.

What happens here when you submit a printout of the results, you get access to the Result property for each task. This blocks the execution of the task, so you wait 5 seconds in WaitAll, and then another 5 seconds when you print the result of the 10 second task.

In accordance with your stated intention, you need to check the status of the task before accessing the result, since your intention is not to block it, but only print it if it is already completed:

 int[] results = new int[tasks.Length]; for (int i = 0; i < tasks.Length; i++) { if (tasks[i].IsCompleted) { Console.WriteLine(tasks[i].Result); } } 

By the way, you can show that “block on Result” is what happens in the source code by simply adding some simple time checks (for example, using a stopwatch, for example)

 Task<int>[] tasks = new Task<int>[] { Task.Factory.StartNew<int>(()=> { Thread.Sleep(10000); return 1; }), Task.Factory.StartNew<int>(()=> { Thread.Sleep(3000); return 2; }) }; TimeSpan timeSpan = new TimeSpan(0, 0, 5); var stopwatch = Stopwatch.StartNew(); Task.WaitAll(tasks, timeSpan); Console.WriteLine("WaitAll took {0} seconds", stopwatch.Elapsed.TotalSeconds); int[] results = new int[tasks.Length]; for (int i = 0; i < tasks.Length; i++) { stopwatch = Stopwatch.StartNew(); Console.WriteLine(tasks[i].Result); Console.WriteLine("Printing result took {0} seconds", stopwatch.Elapsed.TotalSeconds); } 

This gives console output:

 WaitAll took 4.9996961 seconds 1 Printing result took 5.0050012 seconds 2 Printing result took 0.0004338 seconds 
+11
source

try converting the time interval to

 TimeSpan span = new TimeSpan(0, 0, 0, 10, 0); //TimeSpan(Days, hours, minutes, seconds, milliseconds); 
0
source

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


All Articles