Domine o CancellationToken no C#: Cancelamento Eficiente

Imagina iniciar um download enorme e perceber que não precisa mais dele. Você clica em "cancelar" e... nada acontece! O programa trava, a UI congela e o arquivo continua consumindo recursos. 😱 No mundo assíncrono⚡ Async/Await: Programação Assíncrona sem Callbacks!⚡ Async/Await: Programação Assíncrona sem Callbacks!Aprenda a aplicar Async/Await em C# para criar aplicações responsivas, evitar travamentos e melhorar a escalabilidade com exemplos práticos e dicas essenciais. do C#, o CancellationToken é seu botão de emergência para🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)Descubra como automatizar repetições em C# utilizando loops for e while com exemplos práticos que evitam erros e otimizam seu código. Aprenda mais! evitar esses desastres. Vamos explorar como dominar essa ferramenta essencial!

→ Neste artigo você vai aprender:

Tabela de Conteúdo🔗

O que é o CancellationToken?🔗

O CancellationToken é um mecanismo do .NET que permite que tarefas ou métodos🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência. assíncronos escutem um “pedido de cancelamento” vindo de uma fonte externa, chamada de CancellationTokenSource. Em termos simples:

Quando📊 Behavior-Driven Development: Testes que Todo Mundo Entende!📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. você dispara o cancelamento no CancellationTokenSource, todos os métodos🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência. que estão “escutando” esse token podem agir de forma apropriada, interrompendo suas operações.

Como Funciona?🔗

1. Você cria um CancellationTokenSource.

2. Você obtém o token (do tipo🧠 Variáveis em C#: Onde os Dados Ganham Vida (e Nome!)🧠 Variáveis em C#: Onde os Dados Ganham Vida (e Nome!)Descubra como as variáveis em C# funcionam, com exemplos do mundo real, boas práticas de nomeação e dicas para otimizar seu código. CancellationToken) por meio da propriedade⚡ Propriedades: Get e Set com Elegância (e sem Campos Privados Bagunçados)!⚡ Propriedades: Get e Set com Elegância (e sem Campos Privados Bagunçados)!Aprenda como utilizar propriedades em C# para encapsular dados, validar informações e manter um código organizado, seguro e de fácil manutenção. Token.

3. Passa o token para o(s) método🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência.(s) que deseja poder cancelar.

4. No seu método🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência., você verifica periodicamente se o token foi “sinalizado” para cancelamento.

5. Se houver cancelamento, você interrompe a execução (seja retornando, lançando exceção ou limpando recursos📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!Descubra os fundamentos do REST e boas práticas para criar APIs simples, escaláveis e eficientes. Domine métodos HTTP e status codes com exemplos práticos.).

Em essência, o cancelamento é cooperativo: o chamador pede para cancelar, e o método🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência. decide quando📊 Behavior-Driven Development: Testes que Todo Mundo Entende!📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. e como efetivamente parar.

Exemplo Prático com Tasks🔗

Imagine que você tem uma Task que processa um relatório grande. Vamos criar📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!Descubra os fundamentos do REST e boas práticas para criar APIs simples, escaláveis e eficientes. Domine métodos HTTP e status codes com exemplos práticos. um exemplo simples, onde a cada laço verificamos se houve cancelamento:

using System;
using System.Threading;
using System.Threading.Tasks;
public class RelatorioService
{
    public async Task ProcessarRelatorioAsync(CancellationToken token)
    {
        Console.WriteLine("Iniciando processamento...");
        // Simula um processamento em 10 etapas
        for (int i = 1; i <= 10; i++)
        {
            // Verifica a cada iteração se houve pedido de cancelamento
            if (token.IsCancellationRequested)
            {
                Console.WriteLine("Cancelamento detectado. Limpando recursos...");
                // Se necessário, faça limpeza aqui
                return; // ou lance OperationCanceledException
            }
            // Simula algum trabalho
            await Task.Delay(1000);
            Console.WriteLine($"Etapa {i} concluída.");
        }
        Console.WriteLine("Processamento finalizado!");
    }
}
// ------------------------------------
// Exemplo de uso:
public class Program
{
    public static async Task Main()
    {
        var cts = new CancellationTokenSource();
        var service = new RelatorioService();
        // Dispara a Task que pode ser cancelada
        var tarefa = service.ProcessarRelatorioAsync(cts.Token);
        // Espera 3 segundos e depois solicita cancelamento
        await Task.Delay(3000);
        cts.Cancel();
        // Aguarda a finalização da Task
        await tarefa;
    }
}

No exemplo acima:

Cancelando Operações em Fluxos Reais🔗

Muitas vezes, seu código tem várias camadas (por exemplo, uma camada de serviço, outra de repositório🤝 GitHub Básico: Versionamento para Iniciantes!🤝 GitHub Básico: Versionamento para Iniciantes!Descubra como o GitHub facilita colaboração, versionamento e organização de código com este tutorial prático e essencial para desenvolvedores iniciantes.). O CancellationToken pode atravessar essas camadas, sendo passado como parâmetro para métodos🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência. mais profundos que também podem precisar cancelar operações em cascata. Por exemplo, a chamada a um serviço externo, como uma API🌍 Projeto: API de E-Commerce com ASP.NET Core e SQL Server!🌍 Projeto: API de E-Commerce com ASP.NET Core e SQL Server!Aprenda a construir uma API robusta para e-commerce com ASP.NET Core, EF Core, JWT e Swagger, validando suas habilidades em um projeto prático real. HTTP:

public async Task<string> BuscarDadosEmApiAsync(
    CancellationToken token)
{
    using var httpClient = new HttpClient();
    httpClient.Timeout = TimeSpan.FromSeconds(30);
    var response = await httpClient.GetAsync(
        "https://api.exemplo.com/dados",
        token); // Aqui passamos o token também
    response.EnsureSuccessStatusCode();
    return await response.Content.ReadAsStringAsync();
}

Se o token for cancelado, a requisição HTTP também será afetada e interrompida (sempre que a biblioteca🎮 Projeto: Sistema de Gerenciamento de Biblioteca com OOP Puro!🎮 Projeto: Sistema de Gerenciamento de Biblioteca com OOP Puro!Descubra como desenvolver um sistema de biblioteca eficiente utilizando conceitos de Orientação a Objetos em C#. Mergulhe neste tutorial prático e desafiador! usada der suporte a esse cancelamento).

Boas Práticas e Cuidados🔗

1. Checagem Periódica: se o método é longo, verifique o token em intervalos importantes (laços, métodos🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência. internos, etc.).

2. OperationCanceledException: lançar essa exceção💥 Try/Catch: Domine Exceções antes que Elas Dominem Você!💥 Try/Catch: Domine Exceções antes que Elas Dominem Você!Descubra como tratar exceções em C# com práticas eficientes utilizando try/catch. Aprenda a gerenciar erros e aumentar a robustez do seu código. é um modo “padrão” de avisar que a operação foi cancelada voluntariamente. Você pode usá-la em vez de apenas return.

3. Cancelamento “Aninhado”: se você cria um token dentro de outro token (com CancellationTokenSource.CreateLinkedTokenSource), pode combinar sinais de cancelamento de diferentes origens.

4. Liberar Recursos📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!Descubra os fundamentos do REST e boas práticas para criar APIs simples, escaláveis e eficientes. Domine métodos HTTP e status codes com exemplos práticos.: se a operação for cancelada, garanta que recursos📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!Descubra os fundamentos do REST e boas práticas para criar APIs simples, escaláveis e eficientes. Domine métodos HTTP e status codes com exemplos práticos. pesados (conexões, arquivos abertos) sejam adequadamente finalizados.

5. Evite Forçar: lembre-se de que o cancelamento é cooperativo. O método🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência. que recebeu o token decide como interromper. Não finalize abruptamente a Task sem chance de liberar recursos📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!Descubra os fundamentos do REST e boas práticas para criar APIs simples, escaláveis e eficientes. Domine métodos HTTP e status codes com exemplos práticos..

Ao adotar CancellationToken em suas operações assíncronas, você dá flexibilidade ao usuário (ou a outras partes do sistema) de interromper processos demorados sem travar a aplicação. Esse recurso de cancelamento melhora a experiência🌐 LinkedIn para Devs .NET: Perfil que Atrai Recrutadores!🌐 LinkedIn para Devs .NET: Perfil que Atrai Recrutadores!Aprenda a otimizar seu perfil LinkedIn com dicas essenciais para devs .NET. Conquiste oportunidades e destaque suas habilidades!, economiza recursos computacionais e torna seu sistema mais responsivo a imprevistos.

O Problema das Operações "Travadas"🔗

// SEM cancelamento - Perigo!
async Task ProcessarDadosDemorados()
{
    await Task.Delay(10000); // Operação bloqueante
    // Continua mesmo se usuário quiser cancelar ❌
}

Situações problemáticas típicas:

1. UI não responde durante operações longas

2. Requisições HTTP que não podem ser abortadas

3. Processamentos em background consumindo recursos📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!Descubra os fundamentos do REST e boas práticas para criar APIs simples, escaláveis e eficientes. Domine métodos HTTP e status codes com exemplos práticos. desnecessariamente

Uso Básico em Métodos Assíncronos🔗

async Task OperacaoDemoradaAsync(CancellationToken cancellationToken)
{
    for (int i = 0; i < 100; i++)
    {
        cancellationToken.ThrowIfCancellationRequested(); // Verifica cancelamento
        await ProcessarItemAsync(i);
        await Task.Delay(100, cancellationToken); // Delay cancelável
    }
}
// Chamada:
var cts = new CancellationTokenSource();
var task = OperacaoDemoradaAsync(cts.Token);
// Cancela após 5 segundos (ou por ação do usuário):
cts.CancelAfter(5000);

Cancelando Operações Síncronas🔗

void ProcessamentoSincrono(CancellationToken token)
{
    foreach (var item in collection)
    {
        token.ThrowIfCancellationRequested();
        // Para operações MUITO longas:
        if (token.IsCancellationRequested)
        {
            // Libera recursos e sai graciosamente
            return;
        }
        ProcessarItem(item);
    }
}

Cenários Comuns de Uso🔗

CenárioImplementação Típica
Requisições HTTPHttpClient.GetAsync(url, cancellationToken)
Queries EF CoreToListAsync(cancellationToken)
Uploads/DownloadsStream operations with token checks
Processamento em loteLoop com verificação periódica do token

Exemplo com HttpClient:

async Task<string> BaixarSiteAsync(string url, CancellationToken token)
{
    using var client = new HttpClient();
    var response = await client.GetAsync(url, token); // Passa o token diretamente
    return await response.Content.ReadAsStringAsync();
}

Exemplo Prático: Download com Cancelamento🔗

public class DownloadService
{
    private CancellationTokenSource _cts;
    public async Task IniciarDownloadAsync(string url, IProgress<int> progress)
    {
        _cts = new CancellationTokenSource();
        try
        {
            using var client = new HttpClient();
            var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, _cts.Token);
            using var stream = await response.Content.ReadAsStreamAsync();
            var buffer = new byte[8192];
            int bytesRead;
            int totalRead = 0;
            while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, _cts.Token)) > 0)
            {
                totalRead += bytesRead;
                progress.Report(totalRead);
                // Simula processamento adicional
                await Task.Delay(100, _cts.Token);
            }
        }
        catch (OperationCanceledException)
        {
            // Limpeza específica do cancelamento
            Console.WriteLine("Download cancelado pelo usuário");
        }
        finally
        {
            _cts.Dispose();
            _cts = null;
        }
    }
    public void CancelarDownload()
    {
        _cts?.Cancel();
    }
}

Checkpoints de Aprendizado🔗

1. Você sabe diferenciar CancellationTokenSource de CancellationToken?

2. Consegue implementar cancelamento em métodos🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência. síncronos e assíncronos?

3. Sabe quais APIs🌍 Projeto: API de E-Commerce com ASP.NET Core e SQL Server!🌍 Projeto: API de E-Commerce com ASP.NET Core e SQL Server!Aprenda a construir uma API robusta para e-commerce com ASP.NET Core, EF Core, JWT e Swagger, validando suas habilidades em um projeto prático real. do .NET já suportam nativamente cancellation tokens?

4. Entende como evitar resource leaks ao cancelar operações?

Próximo passo: Experimente adicionar📦 List<T>: Dinamismo além dos Arrays!📦 List<T>: Dinamismo além dos Arrays!Descubra como utilizar List<T> em C# de forma eficiente. Aprenda a criar, manipular e otimizar listas para diferentes cenários com exemplos práticos. cancelamento a um método existente em seu código e teste com diferentes cenários de timeout! 🚀

Autor: Marcelo V. Souza - Engenheiro de Sistemas e Entusiasta em IoT e Desenvolvimento de Software, com foco em inovação tecnológica.

Referências🔗

Compartilhar artigo

Artigos Relacionados