Inicio > Cursos > C# > Async/Await y Tasks
C#C# ModernoLección 17 de 20

Async/Await y Tasks

C# introdujo async/await en 2012, tres años antes que JavaScript. Task<T> es el equivalente de Promise<T>: representa una operación que se completará en el futuro. La palabra async marca un método como asíncrono y await espera que una Task complete sin bloquear el hilo.

El resultado práctico: tu app puede hacer peticiones HTTP, leer archivos o acceder a la base de datos sin congelar la interfaz de usuario o desperdiciar hilos del servidor esperando.

C# tiene capacidades de concurrencia más avanzadas que JavaScript. Task.WhenAll ejecuta múltiples Tasks en paralelo real (no secuencial como await t1; await t2) y espera que todas terminen. CancellationToken permite cancelar operaciones en vuelo: si el usuario abandona la página, puedes cancelar la consulta a la base de datos. IAsyncEnumerable permite streaming asíncrono: procesa elementos uno por uno conforme llegan en lugar de esperar todos juntos.

using System.Net.Http;

// async method devuelve Task o Task<T>
public async Task<string> ObtenerDatosAsync(string url) {
    using var cliente = new HttpClient();
    
    try {
        var respuesta = await cliente.GetAsync(url);
        respuesta.EnsureSuccessStatusCode();
        return await respuesta.Content.ReadAsStringAsync();
    } catch (HttpRequestException ex) {
        Console.WriteLine($"Error HTTP: {ex.Message}");
        throw;
    }
}

// Paralelismo con Task.WhenAll
public async Task ProcesarParaleloAsync() {
    var tarea1 = ObtenerDatosAsync("https://api.ejemplo.com/users");
    var tarea2 = ObtenerDatosAsync("https://api.ejemplo.com/posts");
    
    // Se ejecutan EN PARALELO
    var resultados = await Task.WhenAll(tarea1, tarea2);
    Console.WriteLine(resultados[0]); // Resultado de tarea1
    Console.WriteLine(resultados[1]); // Resultado de tarea2
}

// Task.WhenAny - la que termine primero
public async Task<string> ConTimeout(string url, int ms) {
    var solicitud = ObtenerDatosAsync(url);
    var timeout = Task.Delay(ms);
    
    var ganadora = await Task.WhenAny(solicitud, timeout);
    if (ganadora == timeout)
        throw new TimeoutException("Tiempo agotado");
    return await solicitud;
}

// CancellationToken
public async Task OperacionCancelableAsync(CancellationToken ct) {
    for (int i = 0; i < 10; i++) {
        ct.ThrowIfCancellationRequested();
        await Task.Delay(1000, ct);
        Console.WriteLine($"Paso {i + 1}");
    }
}

var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(5));
await OperacionCancelableAsync(cts.Token);

// IAsyncEnumerable (C# 8+) - streaming
public async IAsyncEnumerable<int> GenerarAsync() {
    for (int i = 0; i < 5; i++) {
        await Task.Delay(100);
        yield return i;
    }
}
await foreach (var n in GenerarAsync()) Console.WriteLine(n);
Consejo⚡ Task.WhenAll ejecuta múltiples tareas EN PARALELO. await tarea1; await tarea2; es SECUENCIAL y más lento. Usa WhenAll siempre que puedas.
← Delegates, Events y LambdasPattern Matching y Expresiones →

Practica esta lección

Resuelve los ejercicios del curso de C# en la app, gratis y con corrección automática.

Empezar a practicar