I've been trying for a while to get something I thought would be simple working with .NET 4.5
I want to fire off two long running tasks at same time and collect the
results in in the best C# 4.5 (RTM) way
The following works but I don't like it because:
- I want
Sleep
to be an async method so it canawait
other methods - It just looks clumsy with
Task.Run()
- I don't think this is even using any new language features at all!
Working code:
public static void Go()
{
Console.WriteLine("Starting");
var task1 = Task.Run(() => Sleep(5000));
var task2 = Task.Run(() => Sleep(3000));
int totalSlept = task1.Result + task2.Result;
Console.WriteLine("Slept for a total of " + totalSlept + " ms");
}
private static int Sleep(int ms)
{
Console.WriteLine("Sleeping for " + ms);
Thread.Sleep(ms);
Console.WriteLine("Sleeping for " + ms + " FINISHED");
return ms;
}
Non working code:
Update: This actually works and is the correct way to do it, the only problem is the Thread.Sleep
This code doesn't work because the call to Sleep(5000)
immediately starts the task running so Sleep(1000)
doesn't run until it has completed. This is true even though Sleep
is async
and I'm not using await
or calling .Result
too soon.
I thought maybe there is a way to get a non-running Task<T>
by calling an async
method so I could then call Start()
on the two tasks, but I can't figure out how to get a Task<T>
from calling an async method.
public static void Go()
{
Console.WriteLine("Starting");
var task1 = Sleep(5000); // blocks
var task2 = Sleep(1000);
int totalSlept = task1.Result + task2.Result;
Console.WriteLine("Slept for " + totalSlept + " ms");
}
private static async Task<int> Sleep(int ms)
{
Console.WriteLine("Sleeping for " + ms);
Thread.Sleep(ms);
return ms;
}
It's weekend now!
Unfortunately, if you have another awaits in your methods, Task.WhenAll() will not help you. Async methods are not parallel.
For real parallel execution you should start new Tasks manually e.g. using Task.Run() or ConfigureAwait(false).
Look here for details: https://www.wintellect.com/tasks-are-still-not-threads-and-async-is-not-parallel/
This article helped explain a lot of things. It's in FAQ style.
Async/Await FAQ
This part explains why
Thread.Sleep
runs on the same original thread - leading to my initial confusion.To answer this point:
you can maybe rewrite the
Sleep
function like this:running this code will output :
You should use Task.Delay instead of Sleep for async programming and then use Task.WhenAll to combine the task results. The tasks would run in parallel.