Anulowanie zadań asynchronicznych po upływie czasu

Możesz anulować operację asynchroniczną po upływie określonego czasu przy użyciu CancellationTokenSource.CancelAfter metody , jeśli nie chcesz czekać na zakończenie operacji. Ta metoda planuje anulowanie wszelkich skojarzonych zadań, które nie są wykonywane w okresie wyznaczonym przez CancelAfter wyrażenie.

W tym przykładzie dodamy kod opracowany w sekcji Anuluj listę zadań (C#), aby pobrać listę witryn internetowych i wyświetlić długość zawartości każdego z nich.

W tym samouczku opisano następujące czynności:

  • Aktualizowanie istniejącej aplikacji konsolowej .NET
  • Planowanie anulowania

Wymagania wstępne

Dla tego samouczka wymagane są następujące elementy:

Aktualizowanie punktu wejścia aplikacji

Zastąp istniejącą Main metodę następującym kodem:

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.");
}

Zaktualizowana Main metoda zapisuje kilka komunikatów instruktażowych w konsoli programu . W programie try-catchwywołanie w celu CancellationTokenSource.CancelAfter(Int32) zaplanowania anulowania. Spowoduje to zasygnalizację anulowania po upływie określonego czasu.

Następnie oczekiwana SumPageSizesAsync jest metoda . Jeśli przetwarzanie wszystkich adresów URL odbywa się szybciej niż zaplanowane anulowanie, aplikacja kończy się. Jeśli jednak zaplanowane anulowanie zostanie wyzwolone przed przetworzeniem wszystkich adresów URL, OperationCanceledException zostanie zwrócony błąd.

Przykładowe dane wyjściowe aplikacji

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.

Kompletny przykład

Poniższy kod jest kompletnym tekstem pliku Program.cs w tym przykładzie.

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;
    }
}

Zobacz też