Partilhar via


Cancelar tarefas assíncronas após um período de tempo

Você pode cancelar uma operação assíncrona após um período de tempo usando o CancellationTokenSource.CancelAfter método se não quiser esperar que a operação seja concluída. Este método agenda o cancelamento de quaisquer tarefas associadas que não sejam concluídas dentro do período de tempo designado pela CancelAfter expressão.

Este exemplo adiciona ao código desenvolvido em Cancelar uma lista de tarefas (C#) para baixar uma lista de sites e exibir o comprimento do conteúdo de cada um.

Este tutorial aborda:

  • Atualizando um aplicativo de console .NET existente
  • Agendar um cancelamento

Pré-requisitos

Neste tutorial necessita do seguinte:

Atualizar o ponto de entrada do aplicativo

Substitua o método existente Main pelo seguinte:

static async Task Main()
{
    Console.WriteLine("Application started.");

    try
    {
        s_cts.CancelAfter(3500);

        await SumPageSizesAsync();
    }
    catch (OperationCanceledException)
    {
        Console.WriteLine("\nTasks cancelled: timed out.\n");
    }
    finally
    {
        s_cts.Dispose();
    }

    Console.WriteLine("Application ending.");
}

O método atualizado Main grava algumas mensagens de instrução no console. Dentro do try-catch, uma chamada para CancellationTokenSource.CancelAfter(Int32) agendar um cancelamento. Isso sinalizará o cancelamento após um período de tempo.

Em seguida, o SumPageSizesAsync método é aguardado. Se o processamento de todos os URLs ocorrer mais rápido do que o cancelamento agendado, o aplicativo será encerrado. No entanto, se o cancelamento agendado for acionado antes que todos os URLs sejam processados, um OperationCanceledException será lançado.

Exemplo de saída de aplicativo

Application started.

https://learn.microsoft.com                                       37,357
https://learn.microsoft.com/aspnet/core                           85,589
https://learn.microsoft.com/azure                                398,939
https://learn.microsoft.com/azure/devops                          73,663

Tasks cancelled: timed out.

Application ending.

Exemplo completo

O código a seguir é o texto completo do arquivo Program.cs para o exemplo.

using System.Diagnostics;

class Program
{
    static readonly CancellationTokenSource s_cts = new CancellationTokenSource();

    static readonly HttpClient s_client = new HttpClient
    {
        MaxResponseContentBufferSize = 1_000_000
    };

    static readonly IEnumerable<string> s_urlList = new string[]
    {
            "https://learn.microsoft.com",
            "https://learn.microsoft.com/aspnet/core",
            "https://learn.microsoft.com/azure",
            "https://learn.microsoft.com/azure/devops",
            "https://learn.microsoft.com/dotnet",
            "https://learn.microsoft.com/dynamics365",
            "https://learn.microsoft.com/education",
            "https://learn.microsoft.com/enterprise-mobility-security",
            "https://learn.microsoft.com/gaming",
            "https://learn.microsoft.com/graph",
            "https://learn.microsoft.com/microsoft-365",
            "https://learn.microsoft.com/office",
            "https://learn.microsoft.com/powershell",
            "https://learn.microsoft.com/sql",
            "https://learn.microsoft.com/surface",
            "https://learn.microsoft.com/system-center",
            "https://learn.microsoft.com/visualstudio",
            "https://learn.microsoft.com/windows",
            "https://learn.microsoft.com/maui"
    };

    static async Task Main()
    {
        Console.WriteLine("Application started.");

        try
        {
            s_cts.CancelAfter(3500);

            await SumPageSizesAsync();
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("\nTasks cancelled: timed out.\n");
        }
        finally
        {
            s_cts.Dispose();
        }

        Console.WriteLine("Application ending.");
    }

    static async Task SumPageSizesAsync()
    {
        var stopwatch = Stopwatch.StartNew();

        int total = 0;
        foreach (string url in s_urlList)
        {
            int contentLength = await ProcessUrlAsync(url, s_client, s_cts.Token);
            total += contentLength;
        }

        stopwatch.Stop();

        Console.WriteLine($"\nTotal bytes returned:  {total:#,#}");
        Console.WriteLine($"Elapsed time:          {stopwatch.Elapsed}\n");
    }

    static async Task<int> ProcessUrlAsync(string url, HttpClient client, CancellationToken token)
    {
        HttpResponseMessage response = await client.GetAsync(url, token);
        byte[] content = await response.Content.ReadAsByteArrayAsync(token);
        Console.WriteLine($"{url,-60} {content.Length,10:#,#}");

        return content.Length;
    }
}

Consulte também