2

I understand difference between Task.Run and Task.Factory.StartNew but what is going on when we just assign async method to some local variable ? Would those 3 examples behave identically ?

Example 1

var task1 = GetUsersAsync();
var task2 = GetCarsAsync();

await Task.WaitAll(task1,task2)

Example 2

var task1 = Task.Run(() =>  GetUsersAsync());
var task2 = Task.Run(() =>  GetCarsAsync());

await Task.WaitAll(task1,task2)

Example 3

var task1 = Task.Run(async() => await GetUsersAsync());
var task2 = Task.Run(async() => await GetCarsAsync());

await Task.WaitAll(task1,task2)
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Spam
  • 179
  • 10
  • *we just assign async method to some local variable*. But that's *not* what's happening. It's starting the async method and returning a `Task` that represents the running asynchronous method. The other two are starting a *different* `Task`. That `Task` starts a `Task` representing the asynchronous work. – Daniel Mann Apr 05 '23 at 19:57

1 Answers1

2

Would those 3 examples behave identically

2nd and 3rd will not differ in behaviour (except for the 3rd generating redundant async state machine, compiler can even suggest to remove async-await here - @sharplab.io)

As for the 1st vs 2nd/3rd - it depends on actual implementation of GetUsersAsync, GetCarsAsync, if they are not truly async or contain significant CPU-bound portion before first await then that portion would be handled by the same thread which executes the calling method. I.e:

var startNew = Stopwatch.StartNew();

var task1 = GetUsersAsync();
var task2 = GetCarsAsync();

await Task.WhenAll(task1,task2);

Console.WriteLine(startNew.ElapsedMilliseconds); // Prints ~ 2100

async Task GetUsersAsync()
{
    Thread.Sleep(1000); // simulate CPU-bound work, note that changing order will change the behavior 
    await Task.Delay(100);
}

async Task GetCarsAsync()
{
    Thread.Sleep(1000);
    await Task.Delay(100);
}

While Task.Run approach will schedule the task on thread pool and return immediately:

var startNew = Stopwatch.StartNew();

var task1 = Task.Run(GetUsersAsync);
var task2 = Task.Run(GetCarsAsync);

await Task.WhenAll(task1,task2);

Console.WriteLine(startNew.ElapsedMilliseconds); // Prints ~ 1100

P.S.

Not very relevant in this particular case, but still very useful for general understanding article - Eliding Async and Await by Stephen Cleary.

Guru Stron
  • 102,774
  • 10
  • 95
  • 132