Mackovic
Mackovic

Reputation: 35

How to make one task run after a collection of tasks has finished in C#?

I have a collection of tasks that have to finish before one last task is run. Specifically:

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        var task1 = Task.Run(() =>
        {
            Thread.Sleep(5000);
            Console.WriteLine("Task1");
        });

        var task2 = Task.Run(() =>
        {
            Thread.Sleep(5000);
            Console.WriteLine("Task2");
        });

        var task3 = Task.Run(() =>
        {
            Thread.Sleep(5000);
            Console.WriteLine("Task2");
        });

        var last = Task.Run(() =>
        {
            Console.WriteLine("Last");
        });

        var tasks = new List<Task>();
        tasks.Add(task1);
        tasks.Add(task2);
        tasks.Add(task3);

        await Task.WhenAll(tasks).ContinueWith(t => last);
    }

Currently they finish like this:

Last
Task2
Task3
Last1

I want them to finish like this:

Task1
Task2
Task3
Last

The order of first 3 does not matter, what matters is that Last task finishes last. I cannot block the thread or wait for the collection to finish and similar stuff, only the Last task has to perform after first three are done.

Upvotes: 2

Views: 1912

Answers (2)

Henk Holterman
Henk Holterman

Reputation: 273784

    //var last = Task.Run(() =>
    //{
    //    Console.WriteLine("Last");
    //});

    var tasks = new List<Task>();
    tasks.Add(task1);
    tasks.Add(task2);
    tasks.Add(task3);

    await Task.WhenAll(tasks);  //.ContinueWith(t => last);

    Task.Run(() =>
    {
        Console.WriteLine("Last");
    });

Upvotes: 2

Stephen Cleary
Stephen Cleary

Reputation: 457302

Tasks are created "hot", i.e., already in-progress. If you want to delay the starting of a task, then use a delegate (Func<Task>) or a separate async method.

I like local async methods for this kind of behavior:

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
  async Task Task1() => Task.Run(() =>
  {
    Thread.Sleep(5000);
    Console.WriteLine("Task1");
  });

  async Task Task2() => Task.Run(() =>
  {
    Thread.Sleep(5000);
    Console.WriteLine("Task2");
  });

  async Task Task3() => Task.Run(() =>
  {
    Thread.Sleep(5000);
    Console.WriteLine("Task2");
  });

  async Task Last() => Task.Run(() =>
  {
    Console.WriteLine("Last");
  });

  var tasks = new List<Task>();
  tasks.Add(Task1());
  tasks.Add(Task2());
  tasks.Add(Task3());

  await Task.WhenAll(tasks);
  await Last();
}

P.S. Don't use ContinueWith.

Upvotes: 3

Related Questions