Sdílet prostřednictvím


Zrušení asynchronních úloh po určité době

Asynchronní operaci můžete po určité době zrušit pomocí CancellationTokenSource.CancelAfter metody, pokud nechcete čekat na dokončení operace. Tato metoda naplánuje zrušení všech přidružených úkolů, které nejsou dokončeny během časového období určeného výrazem CancelAfter .

Tento příklad přidá do kódu vyvinutého v části Zrušit seznam úkolů (C#) ke stažení seznamu webů a k zobrazení délky obsahu každého z nich.

Tento kurz zahrnuje:

  • Aktualizace existující konzolové aplikace .NET
  • Naplánování zrušení

Požadavky

V tomto kurzu budete potřebovat následující:

Aktualizace vstupního bodu aplikace

Nahraďte existující Main metodu následujícím kódem:

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

Aktualizovaná Main metoda zapisuje do konzoly několik instrukčních zpráv. V rámci try-catchvolání naplánuje CancellationTokenSource.CancelAfter(Int32) zrušení. To bude signalizovat zrušení po určité době.

V dalším kroku se očekává metoda SumPageSizesAsync . Pokud zpracování všech adres URL proběhne rychleji než plánované zrušení, aplikace skončí. Pokud se však plánované zrušení aktivuje před zpracováním všech adres URL, OperationCanceledException vyvolá se vyvolá.

Příklad výstupu aplikace

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.

Kompletní příklad

Následující kód je úplný text souboru Program.cs pro příklad.

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

Viz také