user3071284
user3071284

Reputation: 7100

Process a list of tasks without concurrency

Given this list:

var tasks = new List<Task>
{
    MyMethod1,
    MyMethod2,
    MyMethod3
};

And these methods:

async Task MyMethod1()
{
    await SomeOtherMethod1();
}

async Task MyMethod2()
{
    await SomeOtherMethod2();
}

async Task MyMethod3()
{
    await SomeOtherMethod3();
}

Is it possible to do this where each task completes in order (no concurrency):

foreach (var task in tasks)
{
    await task;
}

I haven't been able to find any way or examples where this is done. foreach just fires them all off. There is await foreach, but Task doesn't contain a public instance or extension definition for GetAsyncEnumerator.

Upvotes: 2

Views: 430

Answers (3)

user3071284
user3071284

Reputation: 7100

Thank you everyone for the comments and answers. The answers really got me to a solution. I upvoted both answers. I'm putting an answer here, because it updates the code in the question to a working version that I'm using.

var tasks = new List<Func<Task>>
{
    async () => await MyMethod1,
    async () => await MyMethod2,
    async () => await MyMethod3
};
foreach (var task in tasks)
{
    await Task.Run(task);
}

Upvotes: -1

Stephen Cleary
Stephen Cleary

Reputation: 457302

foreach doesn't start the tasks. By convention, tasks are returned "hot" - that is, already running. So, the very fact that you have a list of tasks implies they are already running concurrently.

If you want to create a list of asynchronous actions to execute in the future (i.e., asynchronous delegates), then you want to use a List<Func<Task>> instead of a List<Task>, and then you can foreach over each delegate, invoking it and awaiting the returned task.

Upvotes: 7

Ziv Weissman
Ziv Weissman

Reputation: 4536

Do u mean you want to wait for them to finish one by one by their order?

You can do something simple like a regular for loop (actually foreach should have the same results) and .Wait() or I didn't fully understand what you are trying to achieve...

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace TestStuff
{
    class Program
    {
        static void Main(string[] args)
        {
            Task t1 = new Task(() => {
                Thread.Sleep(2000);
                Console.WriteLine("I'm T1! I'm done!");
            });

            Task t2 = new Task(() => {
                Thread.Sleep(1000);
                Console.WriteLine("I'm T2! I'm done!");
            });


            Task t3 = new Task(() => {
                Thread.Sleep(500);
                Console.WriteLine("I'm T3! I'm done!");
            });


            List<Task> tasks = new List<Task>() { t1, t2, t3 };

            for (int i = 0; i < tasks.Count; i++)
            {
                tasks[i].Start();
                tasks[i].Wait();
            }

        }
    }
}

Upvotes: 1

Related Questions