Megosztás a következőn keresztül:


Tevékenységek listájának lemondása

Az aszinkron konzolalkalmazásokat megszakíthatja, ha nem szeretné megvárni, amíg befejeződik. A jelen témakör példáját követve hozzáadhat egy lemondást egy olyan alkalmazáshoz, amely letölti a webhelyek listájának tartalmát. Az CancellationTokenSource példány társításával számos feladatot megszakíthat az egyes tevékenységekkel. Ha az Enter billentyűt választja, megszakítja az összes még nem befejezett feladatot.

Ez az oktatóanyag az alábbiakkal foglalkozik:

  • .NET-konzolalkalmazás létrehozása
  • Lemondást támogató aszinkron alkalmazás írása
  • Jelzés lemondásának bemutatása

Előfeltételek

Példaalkalmazás létrehozása

Hozzon létre egy új .NET Core-konzolalkalmazást. Létrehozhat egyet a dotnet new console parancs használatával, vagy a Visual Studio alkalmazásával. Nyissa meg a Program.cs fájlt a kedvenc kódszerkesztőjében.

Csere irányelvek használatával

Cserélje le a meglévő using irányelveket a következő nyilatkozatokra:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

Mezők hozzáadása

Program Az osztálydefinícióban adja hozzá a következő három mezőt:

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

A CancellationTokenSource a kért lemondás jelzésére szolgál egy CancellationToken számára. Ez HttpClient lehetővé teszi HTTP-kérések küldését és HTTP-válaszok fogadását. Az s_urlList alkalmazás által feldolgozni kívánt összes URL-címet tartalmazza.

Alkalmazás belépési pont frissítése

A konzolalkalmazás fő belépési pontja a Main metódus. Cserélje le a meglévő metódust a következőre:

static async Task Main()
{
    Console.WriteLine("Application started.");
    Console.WriteLine("Press the ENTER key to cancel...\n");

    Task cancelTask = Task.Run(() =>
    {
        while (Console.ReadKey().Key != ConsoleKey.Enter)
        {
            Console.WriteLine("Press the ENTER key to cancel...");
        }

        Console.WriteLine("\nENTER key pressed: cancelling downloads.\n");
        s_cts.Cancel();
    });

    Task sumPageSizesTask = SumPageSizesAsync();

    Task finishedTask = await Task.WhenAny(new[] { cancelTask, sumPageSizesTask });
    if (finishedTask == cancelTask)
    {
        // wait for the cancellation to take place:
        try
        {
            await sumPageSizesTask;
            Console.WriteLine("Download task completed before cancel request was processed.");
        }
        catch (TaskCanceledException)
        {
            Console.WriteLine("Download task has been cancelled.");
        }
    }

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

A frissített Main metódus mostantól Aszinkron főnek minősül, amely lehetővé teszi aszinkron belépési pontot a végrehajtható fájlba. Néhány oktatóüzenetet ír a konzolra, majd deklarál egy Task példányt, cancelTask néven, amely olvassa a konzol billentyűleütéseit. Ha az Enter billentyűt lenyomja, hívást kezdeményez CancellationTokenSource.Cancel() . Ez jelzi a lemondást. Ezután a sumPageSizesTask változó a SumPageSizesAsync metódus által kap értéket. Ezután a rendszer mindkét feladatot átadja a rendszernek Task.WhenAny(Task[]), amely akkor folytatódik, ha a két tevékenység bármelyike befejeződött.

A következő kódblokk biztosítja, hogy az alkalmazás ne lépjen ki a lemondás feldolgozásáig. Ha az első feladat a cancelTask teljesítése, akkor a sumPageSizeTask-et várják. Ha törölték, amikor várták, ad egy System.Threading.Tasks.TaskCanceledException. A blokk elfogja ezt a kivételt, és kinyomtat egy üzenetet.

Az aszinkron lapméret-összeadás eljárás létrehozása

A Main metódus alá adja hozzá a SumPageSizesAsync metódust.

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

A metódus a példányosítással kezdődik, és elindít egy Stopwatch. Ezután végighalad az s_urlList URL-címeken, és meghívja a ProcessUrlAsync-t. Minden egyes iteráció során a s_cts.Token a ProcessUrlAsync metódusba kerül, és a kód visszatérít egy Task<TResult>-t, ahol a TResult egy egész szám.

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

Folyamatmetódus hozzáadása

Adja hozzá a következő ProcessUrlAsync metódust a SumPageSizesAsync metódus alá:

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

Bármely megadott URL-cím esetében a metódus a client megadott példányt használja a válasz byte[]lekéréséhez. A CancellationToken példányt átadják a HttpClient.GetAsync(String, CancellationToken) és a HttpContent.ReadAsByteArrayAsync() metódusoknak. A token regisztráció a kért lemondásra szolgál. A rendszer az URL-cím és a hossz konzolra írása után adja vissza a hosszt.

Példa alkalmazáskimenetre

Application started.
Press the ENTER key to cancel...

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
https://learn.microsoft.com/dotnet                                67,452
https://learn.microsoft.com/dynamics365                           48,582
https://learn.microsoft.com/education                             22,924

ENTER key pressed: cancelling downloads.

Application ending.

Teljes példa

A következő kód a példához tartozó Program.cs fájl teljes szövege.

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.");
        Console.WriteLine("Press the ENTER key to cancel...\n");

        Task cancelTask = Task.Run(() =>
        {
            while (Console.ReadKey().Key != ConsoleKey.Enter)
            {
                Console.WriteLine("Press the ENTER key to cancel...");
            }

            Console.WriteLine("\nENTER key pressed: cancelling downloads.\n");
            s_cts.Cancel();
        });

        Task sumPageSizesTask = SumPageSizesAsync();

        Task finishedTask = await Task.WhenAny(new[] { cancelTask, sumPageSizesTask });
        if (finishedTask == cancelTask)
        {
            // wait for the cancellation to take place:
            try
            {
                await sumPageSizesTask;
                Console.WriteLine("Download task completed before cancel request was processed.");
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("Download task has been cancelled.");
            }
        }

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

Lásd még

Következő lépések