CodeGym /Cursos /C# SELF /Cancelación de operaciones asíncronas

Cancelación de operaciones asíncronas

C# SELF
Nivel 42 , Lección 4
Disponible

1. Introducción

Cuando arrancas una operación asíncrona (o larga), el usuario (u otro código) puede de repente decidir: "¡Alto! Ya no hace falta. ¡Para!". Por ejemplo, el usuario decidió interrumpir la descarga de un archivo enorme, cerró la ventana del programa o cambió de idea sobre buscar información en una base de datos grande. Sin soporte de cancelación tu programa puede seguir funcionando y consumir recursos inútilmente — no es la mejor muestra de respeto hacia el usuario y el equipo.

Escenarios típicos de cancelación:

  • Cancelar la descarga de un archivo o cancelar el envío de datos.
  • Salir rápidamente de un proceitselfiento complejo por petición del usuario.
  • Al pausar/bruscamente detener una tarea larga que ya no es relevante.

La cancelación es tu ingrediente secreto para aplicaciones amables, responsivas y eficientes.

¿Cómo cancelar operaciones asíncronas en .NET?

En .NET para cancelar tareas largas se usa el concepto de "token de cancelación" (CancellationToken). Es un objeto especial que se pasa a los componentes de la tarea. Si alguien pide cancelar la operación — el token informa al instante a todas las partes interesadas. En la práctica es como una bandera roja: quien la vea primero, se detiene.

En .NET este mecanismo está implementado con dos clases clave:

Importante: el token por sí solo no interrumpe la ejecución del código; solo "señaliza" — y tu aplicación decide cuándo y cómo reaccionar a esa señal.

2. Creamos un token de cancelación y cancelamos una tarea

Veamos cómo funciona con un ejemplo sencillo (vamos a ampliar nuestra aplicación de consola educativa).

Ejemplo: operación asíncrona simple con cancelación


using System;
using System.Threading;
using System.Threading.Tasks;

namespace DemoApp
{
    class Program
    {
        static async Task Main()
        {
            // Create a cancellation token source
            CancellationTokenSource cts = new CancellationTokenSource();

            // Start an asynchronous task
            Task longRunningTask = DoWorkAsync(cts.Token);

            Console.WriteLine("Press any key to cancel the operation...");
            Console.ReadKey();

            // Request cancellation otmenu
            cts.Cancel();

            try
            {
                await longRunningTask;
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("Operation was cancelled byla otmenena!");
            }
        }

        // An asynchronous method that supports cancellation
        static async Task DoWorkAsync(CancellationToken cancellationToken)
        {
            for (int i = 0; i < 10; i++)
            {
                // Check cancellation signal
                cancellationToken.ThrowIfCancellationRequested();

                Console.WriteLine($"Step execution {i + 1}/10...");
                await Task.Delay(1000); // Delay 1 second
            }

            Console.WriteLine("Operation was cancelled zavershena uspeshno!");
        }
    }
}

¿Cómo funciona esto?

- Creamos CancellationTokenSource (cts), desde donde obtenemos el token (cts.Token).
- Paitselfos ese token a nuestra operación asíncrona.
- Dentro de DoWorkAsync() comprobamos regularmente el token con ThrowIfCancellationRequested(). Si el usuario pide cancelar la tarea — ese método lanzará la excepción OperationCanceledException, y la tarea se interrumpirá.
- En Main() esperamos a que se pulse cualquier tecla y llamamos a cts.Cancel() para "señalar" la necesidad de detener la operación.

Si no compruebas cancellationToken.IsCancellationRequested o no llamas a ThrowIfCancellationRequested(), tu tarea seguirá funcionando como si nada — el token es solo una bandera informativa.

3. CancellationToken: ¿cómo está hecho? Y un poco de magia

El token de cancelación es un objeto que se puede pasar fácilmente entre métodos y tareas. Esto da mucha flexibilidad:

  • El mismo token se puede usar en varias operaciones asíncronas y sincrónicas.
  • Puedes organizar una "cancelación grupal" para todas las tareas si varias operaciones usan el token proveniente de un mismo CancellationTokenSource.
  • El token es no intrusivo: incluso si lo ignoras, el código seguirá funcionando igual.

Gestión de la cancelación: ¿dónde y cómo comprobar el token?

Comprobar si la "bandera de cancelación" está levantada se debe hacer donde tenga sentido lógico: en un bucle, en cada paso de un proceitselfiento largo, al pasar de una etapa a otra, etc.


// At any point during the check
if (cancellationToken.IsCancellationRequested)
{
    Console.WriteLine("Operation was cancelled otmenena! Vykhodim...");
    return;
}

// Or like this (shortly throwing exception)
cancellationToken.ThrowIfCancellationRequested();

Normalmente se usa ThrowIfCancellationRequested() — lanza una excepción especial que se puede atrapar en el código que llamó.

4. Métodos asíncronos de la biblioteca estándar

Muchísimas clases y métodos de .NET (especialmente los asíncronos) soportan CancellationToken "de serie". Debes usarlos para detener operaciones de forma "correcta".

Aquí un ejemplo de lectura asíncrona de archivo:


using System.IO;
using System.Threading;
using System.Threading.Tasks;

class FileDemo
{
    public static async Task ReadFileWithCancelAsync(string filePath, CancellationToken cancellationToken)
    {
        using FileStream stream = File.OpenRead(filePath);
        byte[] buffer = new byte[4096];

        int bytesRead;
        while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
        {
            // Processing data...
            // If cancellation was requested, ReadAsync itself throw OperationCanceledException
        }
    }
}

Lee más sobre FileStream.ReadAsync y CancellationToken en la documentación oficial.

5. Matices útiles

Timeout — ¡también es cancelación!

Puedes cancelar operaciones automáticamente tras un tiempo definido. Para eso puedes "programar" el token de cancelación:


// Create CancellationTokenSource with timeout (for example, 5 seconds)
CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

Tras 5 segundos el token se marcará automáticamente y todas las operaciones con él se detendrán en la siguiente comprobación. Es muy útil si no quieres esperar eternamente.

¿Qué pasa al cancelar?

Cuando llamas Cancel() en el source del token, todos los métodos que usan ese token y comprueban su estado se enteran del cambio. Pero si tu código no comprueba el token — la cancelación no ocurrirá.

Un error típico: olvidar pasar el token a todas las operaciones asíncronas y largas. Entonces una parte se cancelará y otra seguirá como si nada.

Visualización: cómo transcurre la cancelación

sequenceDiagram
    participant Main as Hilo principal
    participant CTS as CancellationTokenSource
    participant Task as Tarea asíncrona

    Main->>CTS: crea CTS, obtiene token
    Main->>Task: pasa token a la tarea asíncrona
    Note over Task: La tarea comprueba el token periódicamente
    Main->>CTS: llama a Cancel()
    CTS-->>Task: el token recibe el estado "cancelado"
    Task-->>Main: lanza OperationCanceledException
    Main->>Main: atrapa la excepción y termina el trabajo

¿Dónde se aplica la cancelación de operaciones asíncronas?

  • Descargas asíncronas y peticiones al servidor: se pueden cancelar con mala conexión o si el usuario se cansa.
  • Cálculos pesados: se pueden detener por timeout o por petición del usuario.
  • Operaciones de red, trabajo con archivos, proceitselfiento de grandes colecciones en background.

Con esto termina la introducción a la cancelación de operaciones asíncronas — ahora tu aplicación será no solo rápida, sino también considerada.

6. Consejos y errores típicos

No olvides pasar el token de cancelación a todos los métodos y llamadas que soporten cancellation. Si lo olvidas en algún sitio — la operación puede "quedarse colgada" y no detenerse.

Comprueba el token regularmente — especialmente en bucles largos, procesando archivos o descargando grandes volúmenes. Usa IsCancellationRequested o ThrowIfCancellationRequested().

No intentes "forzar" la terminación de un hilo o tarea desde fuera: el token de cancelación es una petición para que se detengan, no un garrote para pegar al hilo.

Las funciones de la biblioteca estándar como ReadAsync, Delay, HttpClient.SendAsync y muchas otras ya soportan cancelación vía token. ¡Úsalas!

Al manejar la cancelación captura específicamente OperationCanceledException — es la excepción que indica una cancelación correcta por petición.

2
Tarea
C# SELF, nivel 42, lección 4
Bloqueada
Cancelación simple de una tarea usando CancellationToken
Cancelación simple de una tarea usando CancellationToken
1
Cuestionario/control
Operaciones asíncronas con archivos, nivel 42, lección 4
No disponible
Operaciones asíncronas con archivos
Ventajas del trabajo asíncrono con archivos
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION