Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
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
- A legújabb .NET SDK
- Visual Studio Code szerkesztő
- A C# DevKit
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;
}
}