What is the C# equivalent to Promise.all?
Asked Answered
E

3

19

I would like to fetch data from multiple locations from Firebase Realtime Database like described here and here by Frank van Puffelen and I can't find any equivalent to Promise.all in c#. What would be the proper way to do it?

Effable answered 2/2, 2019 at 18:0 Comment(1)
In addition to any answers here, check out this SO answer explaining a Promise equivalent in C#Reproduce
U
25

That you are looking for is Task.WhenAll. You should create as many tasks as the multiple locations from which you want to fetch your data and then feed them in this method.

Underdog answered 2/2, 2019 at 18:3 Comment(2)
I think Task.WhenAll is similar to Promise.allSettled, not Promise.all. There is nothing in .NET similar to Promise.all as far as I know.Clementeclementi
Here's the example that probably should have come with this answer. As @Clementeclementi pointed out, this is more similar to Promise.allSettled than Promise.all - because of static typing, if you have Task<T> instances with different types T, something like Promise.all would lead you into type-casts, which is clunky and unsafe; you're better off with something like Promise.allSettled and simply await again for the results from the tasks that have already been run and resolved in parallel. It's all good. :-)Marquise
C
11

To expand on @Christos's accepted answer:

Task.WhenAll appears to be about as close as you will get for a drop-in replacement for Promise.all. I actually found it to be closer than I initially thought. Here's an example using a JavaScript Promise.all implementation that you may want to replicate in C#:

const [ resolvedPromiseOne, resolvedPromiseTwo ] = await Promise.all([ taskOne, taskTwo ]);

In C# you can do something very similar with Task.WhenAll (assuming they return the same types).

var taskList = new[]
{
  SomeTask(),
  AnotherTask()
};

var completedTasks = await Task.WhenAll(taskList);

// then access them like you would any array
var someTask = completedTasks[0];
var anotherTask = completedTasks[1];

// or just iterate over the array
foreach (var task in completedTasks)
{
  doSomething(task);
}

This assumes they're both in async methods / functions.

Caras answered 11/12, 2019 at 20:23 Comment(2)
these seems to be either obsolete or for a earlier version of .NET than my env.Platas
And what about when they don't return the same types?Grandiloquence
M
-2

So, one way that "should" be able to allow for a similar experience to Promise.all is the following (untested).

var myTaskAsync = myTask(); // do not "await" here.
var myOtherTaskAsync = myOtherTask(); // or here (well, technically you could, but that is confusing)

// that "should" have started both tasks immediately which are now both running.
var myTaskResult = await myTaskAsync;
var myOtherTaskResult = await myOtherTaskAsync;

// Now use the results as you would have, had you done a Promise.all
// if myTaskResult came back first, we now wait to get myOtherTaskResult
// if myOtherTaskResult finished first, then by the time you get to the
//    await for it, it should be returned immediately.
// This is the equivalent of await Promise.all 
Marked answered 22/5 at 14:7 Comment(1)
Awaiting the tasks sequentially is not the same as await Task.WhenAll. If the first task fails, the second will not be awaited, and will become fire-and-forget. Which is a bad idea in general. Please use the await Task.WhenAll, it exists for a reason.Sclar

© 2022 - 2024 — McMap. All rights reserved.