0

I have two async mehotds that not directly related to one another (they do both write out though).. and i don't want either to block the efficiency of the other..

If i place one of the activities in a set of tasks like this:

var list = new List<Task>();

foreach (var t in things)
{
    list.Add(My.MethodAsync(t)); // method returns Task
}

await Task.WhenAll(t);

I know that it will not block, and potentially run in parallel..

If i another async method though though:

var list = new List<Task>();

foreach (var t in things)
{
    list.Add(My.MethodAsync(t)); // method returns Task
}

foreach (var t in things)
{
    await My.OtherAsync(t)); // method returns Task
}

await Task.WhenAll(t);

The Task.WhenAll() needs to wait for the second foreach to complete...

Therefore, is something like this possible / recommend?

var allTasks = new List<Task>();

foreach (var t in things)
{
    allTasks.Add(My.MethodAsync(t)); // method returns Task
    allTasks.Add(My.OtherAsync(t)); // method returns Task
}

await Task.WhenAll(t);

Having typed this out, even though the tasks themselves are independent, it would be nice i guess if an error was raised if both do not output.. hmm

question still stands though ;)

m1nkeh
  • 1,337
  • 23
  • 45
  • 1
    "The Task.WhenAll() needs to wait for the blocking foreach to complete...", not true. The tasks will be running at the same time – Camilo Terevinto Nov 08 '18 at 15:40
  • oh really? i thought the Task.WhenAll(t) would not have kicked off yet, and freed up the main thread? And it couldn't due to the second foreach preventing it.. – m1nkeh Nov 08 '18 at 15:41
  • If `My.MethodAsync(t)` returns a Task, it is already initiated. `WhenAll` will just asynchronously wait for them to complete, if they haven't already – Camilo Terevinto Nov 08 '18 at 15:43
  • 1
    I would take a look at this one reguarding the exceptions. https://stackoverflow.com/questions/25009437/running-multiple-async-tasks-and-waiting-for-them-all-to-complete – Ryan Schlueter Nov 08 '18 at 15:44
  • 1
    `Parallel.Invoke` runs CPU-bound actions in parallel. `Task.WhenAll` and `Task.WaitAll` wait for all tasks to complete. You still need to start them before though. Provided that `MethodAsync` and `OtherAsync` returned started tasks, your second example is fine. – mm8 Nov 08 '18 at 15:45
  • yeah they return tasks... i have updated the original q to show ;) – m1nkeh Nov 08 '18 at 15:47
  • @m1nkeh Returning a task is different than returning an un-started task. Without seeing your implementation, I couldn't tell you which you're doing but if you look [here](https://stackoverflow.com/questions/16066349/how-to-construct-a-task-without-starting-it), you'll find some help in that regard – Woody1193 Nov 08 '18 at 15:52
  • @Woody1193 i am not explicitly trying to async an unstarted task.. so would assume it's started, lets' just assume they are both writing to the file system... – m1nkeh Nov 08 '18 at 15:55
  • @m1nkeh Then you should be fine with the syntax you've provided – Woody1193 Nov 08 '18 at 15:56
  • out of interest it if was unstarted (which to be honest i have not heard of) how would it get started? – m1nkeh Nov 08 '18 at 15:57
  • 1
    @m1nkeh You'd call `task.Start()` – Woody1193 Nov 08 '18 at 16:00

1 Answers1

1
var allTasks = new List<Task>();

foreach (var t in things)
{
    allTasks.Add(My.MethodAsync(t); // method returns Task
    allTasks.Add(My.OtherAsync(t); // method returns Task
}

await Task.WhenAll(t).ConfigureAwait(false);

This will work just fine. As was pointed out in the comments, if your methods return a Task that was started already (see here), then all Task.WhenAll will do is wait asynchronously for the tasks to complete. These tasks may run in parallel if their run-time is long enough that you can start one before the previous finishes. Note that I added ConfigureAwait(false) to your code. Technically, it doesn't actually change what your code is doing as await is done with false as the default but it does clarify your intent so I prefer it when I write asynchronous method calls.

Woody1193
  • 7,252
  • 5
  • 40
  • 90