Having created the following console application I am a little puzzled why it seems to run synchronously instead of asynchronously:
class Program
{
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var total = CreateMultipleTasks();
stopwatch.Stop();
Console.WriteLine("Total jobs done: {0} ms", total.Result);
Console.WriteLine("Jobs done in: {0} ms", stopwatch.ElapsedMilliseconds);
}
static async Task<int> CreateMultipleTasks()
{
var task1 = WaitForMeAsync(5000);
var task2 = WaitForMeAsync(3000);
var task3 = WaitForMeAsync(4000);
var val1 = await task1;
var val2 = await task2;
var val3 = await task3;
return val1 + val2 + val3;
}
static Task<int> WaitForMeAsync(int ms)
{
Thread.Sleep(ms);
return Task.FromResult(ms);
}
}
When running the application, output is:
Total jobs done: 12000 ms
Jobs done in: 12003 ms
I would have expected somehing like:
Total jobs done: 12000 ms
Jobs done in: 5003 ms
Is this because when I use the Thread.Sleep method it stops further execution of the whole application? Or am I missing something important here?
Even when you convert to using Task.Run
or Task.Delay
as other answers suggest, you should avoid using the blocking Task.WaitAll
anywhere inside async
methods, as much as you can. Mixing asynchronous and synchronous code is usually a bad idea, it increases the number of redundantly blocked threads and promotes deadlocks.
Instead, use await Task.WhenAll
and move the blocking wait to the top level (i.e., Main
method in this case):
class Program
{
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var total = CreateMultipleTasks();
total.Wait();
stopwatch.Stop();
Console.WriteLine("Total jobs done: {0} ms", total.Result);
Console.WriteLine("Jobs done in: {0} ms", stopwatch.ElapsedMilliseconds);
}
static async Task<int> CreateMultipleTasks()
{
var task1 = Task.Run(() => WaitForMeAsync(5000));
var task2 = Task.Run(() => WaitForMeAsync(3000));
var task3 = Task.Run(() => WaitForMeAsync(4000));
await Task.WhenAll(new Task[] { task1, task2, task3 });
return task1.Result + task2.Result + task3.Result;
}
static int WaitForMeAsync(int ms)
{
// assume Thread.Sleep is a placeholder for a CPU-bound work item
Thread.Sleep(ms);
return ms;
}
}
On a side note, check Stephen Toub's "Should I expose asynchronous wrappers for synchronous methods?" and "Should I expose asynchronous wrappers for synchronous methods?"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With