C#

C# Fundamentals

19 lessons

Progress0%
1. Introduction to C#
1What is C#?
2. Variables and Data Types
1Data Types in C#
3. Control Flow
ConditionalsLoops
4. Methods
Defining MethodsOptional Parameters and Overloading
5. Object-Oriented Programming
Classes and PropertiesInheritanceInterfaces and Generics
6. LINQ and Async
LINQ Queriesasync/await
7. Exception Handling
try/catch/finally & Exception TypesCustom Exceptions & IDisposable
8. Delegates & Events
Delegates & LambdaEvents & Event Handlers
9. Records & Pattern Matching
Record TypesPattern Matching & Switch Expressions
10. File I/O & JSON
File & Stream OperationsJSON Serialization
All Tutorials
C#LINQ and Async
Lesson 11 of 19 min
Chapter 6 · Lesson 2

async/await

async/await in C#

Asynchronous programming lets your application remain responsive while waiting for I/O operations (network, file, database).

Task<T> Task<T> represents an asynchronous operation that eventually produces a value of type T. Task (without a type parameter) represents an operation that produces no value.

async and await

  • Mark a method with async to enable the await keyword inside it.
  • await suspends the current method until the awaited task completes, without blocking the thread.
  • An async method must return Task, Task<T>, ValueTask<T>, or void (only for event handlers).

Task.WhenAll Run multiple async operations concurrently and wait for all to complete:

csharp
await Task.WhenAll(task1, task2, task3);

Key points:

  • Avoid async void except for event handlers — unhandled exceptions cannot be caught.
  • ConfigureAwait(false) avoids capturing the synchronization context in library code.
  • CPU-bound work belongs on a thread pool via Task.Run(), not as an async method.

Code Examples

async/await basicscsharp
using System;
using System.Threading.Tasks;

class Program {
    static async Task<string> FetchDataAsync(string source) {
        await Task.Delay(100); // simulates I/O
        return $"Data from {source}";
    }

    static async Task ProcessAsync() {
        Console.WriteLine("Starting...");
        string result = await FetchDataAsync("API");
        Console.WriteLine(result);
        Console.WriteLine("Done.");
    }

    static async Task Main() {
        await ProcessAsync();
    }
}

await suspends ProcessAsync while FetchDataAsync runs, then resumes exactly where it left off.

Task.WhenAll for concurrencycsharp
using System;
using System.Threading.Tasks;

class Program {
    static async Task<int> ComputeAsync(int id, int delay) {
        await Task.Delay(delay);
        return id * id;
    }

    static async Task Main() {
        var t1 = ComputeAsync(3, 100);
        var t2 = ComputeAsync(4, 50);
        var t3 = ComputeAsync(5, 75);

        int[] results = await Task.WhenAll(t1, t2, t3);
        foreach (var r in results)
            Console.Write(r + " ");
        Console.WriteLine();
        Console.WriteLine($"Sum: {results[0] + results[1] + results[2]}");
    }
}

Task.WhenAll runs all three tasks concurrently. Total time is ~100ms (the longest), not 225ms (sequential sum).

Quick Quiz

1. What must the return type of an async method be (other than void)?

2. What does `await Task.WhenAll(t1, t2)` do?

Was this lesson helpful?

PreviousNext