Freigeben über


Abbrechen asynchroner Aufgaben nach einem bestimmten Zeitraum

Sie können einen asynchronen Vorgang nach einem gewissen Zeitraum mithilfe der CancellationTokenSource.CancelAfter-Methode abbrechen, wenn Sie nicht auf das Ende des Vorgangs warten möchten. Diese Methode plant den Abbruch aller zugeordneten Aufgaben, die innerhalb des vom CancelAfter-Ausdruck festgelegten Zeitraums nicht abgeschlossen sind.

Dieses Beispiel fügt dem in Abbrechen einer asynchronen Aufgabe oder Aufgabenliste (C#) entwickelten Code Funktionen zum Herunterladen einer Liste von Websites und Anzeigen der Länge der Inhalte jeder Site hinzu.

In diesem Lernprogramm wird Folgendes behandelt:

  • Aktualisieren einer vorhandenen .NET-Konsolenanwendung
  • Planen eines Abbruchs

Voraussetzungen

Für dieses Lernprogramm ist Folgendes erforderlich:

Aktualisieren des Einstiegspunkts der Anwendung

Ersetzen Sie die vorhandene Main-Methode durch Folgendes:

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

Mit der aktualisierten Main-Methode werden einige Anweisungsnachrichten in die Konsole geschrieben. In der try-catch-Anweisung plant ein Aufruf von CancellationTokenSource.CancelAfter(Int32) einen Abbruch. Dadurch wird ein Abbruch nach einem bestimmten Zeitraum signalisiert.

Als Nächstes wird die SumPageSizesAsync-Methode erwartet. Wenn die Verarbeitung aller URLs schneller erfolgt als der geplante Abbruch, wird die Anwendung beendet. Wenn jedoch der geplante Abbruch vor der Verarbeitung aller URLs ausgelöst wird, wird eine OperationCanceledException-Klasse ausgelöst.

Ausgabe der Beispielanwendung

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.

Vollständiges Beispiel

Der folgende Code besteht aus dem vollständigen Text der Program.cs-Datei für das Beispiel.

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

Weitere Informationen