๐ŸŽ“ A1Learner
๐Ÿ”
0 of 38 lessons completed

C# Task Composition

Task composition runs several tasks together and waits for all of them as one group. Task.WhenAll creates that group wait.

Two Slots, Two Tasks

Two Fill tasks write two different slots. Main prints the slots after the group wait completes.

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Fill(string[] slots, int index, string text)
    {
        await Task.Delay(10);
        slots[index] = text;
    }

    static async Task Main(string[] args)
    {
        string[] slots = new string[2];
        Task first = Fill(slots, 0, "Alpha");
        Task second = Fill(slots, 1, "Beta");
        await Task.WhenAll(first, second);
        Console.WriteLine(slots[0]);
        Console.WriteLine(slots[1]);
    }
}

Three Tasks Together

Three Fill tasks start before the await. Each task writes a different slot, so the slot order stays fixed.

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Fill(string[] slots, int index, string text, int delay)
    {
        await Task.Delay(delay);
        slots[index] = text;
    }

    static async Task Main(string[] args)
    {
        string[] slots = new string[3];
        Task first = Fill(slots, 0, "Red", 30);
        Task second = Fill(slots, 1, "Green", 10);
        Task third = Fill(slots, 2, "Blue", 20);
        await Task.WhenAll(first, second, third);
        Console.WriteLine(slots[0]);
        Console.WriteLine(slots[1]);
        Console.WriteLine(slots[2]);
    }
}

Slot Values Added Up

Three tasks store numbers in three slots. Main adds the slots after the wait and prints the total.

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Store(int[] slots, int index, int value)
    {
        await Task.Delay(10);
        slots[index] = value;
    }

    static async Task Main(string[] args)
    {
        int[] slots = new int[3];
        Task first = Store(slots, 0, 10);
        Task second = Store(slots, 1, 20);
        Task third = Store(slots, 2, 30);
        await Task.WhenAll(first, second, third);
        int total = slots[0] + slots[1] + slots[2];
        Console.WriteLine("Total: " + total);
    }
}

Example

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Fill(string[] slots, int index, string text, int delay)
    {
        await Task.Delay(delay);
        slots[index] = text;
    }

    static async Task Main(string[] args)
    {
        string[] slots = new string[3];
        Task first = Fill(slots, 0, "Header ready", 30);
        Task second = Fill(slots, 1, "Body ready", 20);
        Task third = Fill(slots, 2, "Footer ready", 10);
        await Task.WhenAll(first, second, third);
        Console.WriteLine(slots[0]);
        Console.WriteLine(slots[1]);
        Console.WriteLine(slots[2]);
    }
}

Key points

  • Calling an async method starts it and returns its Task.
  • Task.WhenAll takes several tasks and returns one Task for the group.
  • An await on that group Task waits for every task in the group.
  • Each task in this lesson writes its result into its own slot of a shared array.
  • Separate slots keep tasks from overwriting each other.
  • Main prints the slots only after the await completes.
  • The printed order is the slot order, not the order tasks finish in.

In this example, three Fill tasks start together. Each task writes one named slot and no other slot. Main awaits Task.WhenAll until every task has finished. Main then prints the slots in index order.

Note

A task never prints in this lesson. Main does all the printing after the wait.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

When does Main print the slots in a Task.WhenAll program?