26

Hopefully a fairly simple one here. I have a collection of objects, each of which has an async method that I want to call and collect values from. I'd like them to run in parallel. What I'd like to achieve can be summed up in one broken line of code:

IEnumerable<TestResult> results = await Task.WhenAll(myCollection.Select(v => v.TestAsync()));

I've tried various ways of writing this without success. Any thoughts?

4
  • 1
    How does TestAsync look? Commented Nov 10, 2014 at 8:48
  • 2
    This line of code looks OK. What doesn't work exactly? Any compiler error, run-time exception, etc.? Commented Nov 10, 2014 at 9:04
  • I guess his TestAsync() signature was looking like this: public async TestResult TestAsync(), instead of public async Task<TestResult> TestAsync(). Commented Sep 29, 2017 at 20:19
  • Somewhat related: ForEachAsync with Result. Commented Aug 11, 2023 at 17:55

2 Answers 2

21

If the tasks you're awaiting have a result of the same type Task.WhenAll returns an array of them. For example for this class:

public class Test
{
    public async Task<TestResult> TestAsync()
    {
        await Task.Delay(1000); // Imagine an I/O operation.
        return new TestResult();
    }
}

We get these results:

var myCollection = new List<Test>();
myCollection.Add(new Test());

IEnumerable<TestResult> results = await Task.WhenAll(myCollection.Select(v => v.TestAsync()));
Sign up to request clarification or add additional context in comments.

5 Comments

@I3arnon: this is the same code, which OP had written. It's better to clarify, what doesn't work for him.
I've explained what should work and why. I'm waiting for the OP to clarify what doesn't work for him.
I'm an idiot - My TestAsync method was returning a Task rather than a Task<TestResult> - as soon as I changed that, it worked. Thanks for pointing me in the right direction - I couldn't see what was wrong even though it was riht in front of me!
Could you supply an example where TestAsync accepts parameters, and is a static method ?
What worked for me was replacing Task.WaitAll with await Task.WhenAll in this answer
6

Do it like this:

public async Task RunMultipleTasksInParallelAsync()
{
    var tasks = new List<Task<MyResultType>>(); //<---- Add the return type here

    foreach (var item in items)
    {
        var task = DoSomethingAsync();
        tasks.Add(task);
    }

    var myResults = await Task.WhenAll(tasks);
}

public async Task<MyResultType> DoSomethingAsync()
{
    return new MyResultType();
}

Recogize that you have to add the return type into the task list, otherwhise Task.WhenAll will have the return type void.

1 Comment

Thank you! That was the missing piece of the puzzle for me

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.