Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Asynchronní konzolovou aplikaci můžete zrušit, pokud nechcete čekat na dokončení. Podle příkladu v tomto tématu můžete přidat zrušení do aplikace, která stáhne obsah seznamu webů. Mnoho úkolů můžete zrušit přidružením CancellationTokenSource instance k jednotlivým úkolům. Pokud vyberete klávesu Enter , zrušíte všechny úkoly, které ještě nejsou dokončené.
Tento kurz zahrnuje:
- Vytvoření konzolové aplikace .NET
- Psaní asynchronní aplikace, která umožňuje zrušení
- Předvádění rušení signálu
Požadavky
- Nejnovější sada .NET SDK
- editor Visual Studio Code editoru
- C# DevKit
Vytvoření ukázkové aplikace
Vytvořte novou konzolovou aplikaci .NET Core. Můžete ho vytvořit pomocí příkazu dotnet new console
nebo sady Visual Studio. Otevřete soubor Program.cs ve svém oblíbeném editoru kódu.
Nahrazení směrnic using
Nahraďte stávající using
direktivy těmito deklaracemi:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
Přidat pole
Program
Do definice třídy přidejte tato tři pole:
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"
};
K signalizaci požadovaného zrušení u CancellationToken se používá CancellationTokenSource. Zpřístupňuje HttpClient
schopnost odesílat požadavky HTTP a přijímat odpovědi HTTP. Obsahuje s_urlList
všechny adresy URL, které aplikace plánuje zpracovat.
Aktualizace vstupního bodu aplikace
Hlavním vstupním bodem do konzolové aplikace je Main
metoda. Nahraďte existující metodu následujícím kódem:
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.");
}
Aktualizovaná metoda Main
je nyní považována za Async main, což umožňuje asynchronní vstupní bod do spustitelného souboru. Zapíše do konzoly několik instrukčních zpráv a pak deklaruje Task instanci s názvem cancelTask
, která bude číst tahy kláves konzoly. Pokud je stisknutá klávesa Enter , provede se volání CancellationTokenSource.Cancel() . Tím se signalizuje zrušení. Dále je proměnná sumPageSizesTask
přiřazena z SumPageSizesAsync
metody. Oba úkoly se pak předají Task.WhenAny(Task[]), což bude pokračovat po dokončení některého z těchto dvou úkolů.
Další blok kódu zajistí, že se aplikace neukončí, dokud nebude zpracováno zrušení. Pokud je prvním úkolem, který se má dokončit, cancelTask
, očekává se sumPageSizeTask
. Pokud byla zrušena, při čekání vyvolá System.Threading.Tasks.TaskCanceledException. Blok tuto výjimku zachytí a vytiskne zprávu.
Vytvořte asynchronní metodu pro součet velikostí stránek
Pod metodu Main
přidejte metodu SumPageSizesAsync
:
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");
}
Metoda začíná vytvořením instance a spuštěním Stopwatch. Pak prochází každou adresu URL ve s_urlList
a volá ProcessUrlAsync
. Při každé iteraci se předá s_cts.Token
do ProcessUrlAsync
metody a kód vrátí Task<TResult>hodnotu , kde TResult
je celé číslo:
int total = 0;
foreach (string url in s_urlList)
{
int contentLength = await ProcessUrlAsync(url, s_client, s_cts.Token);
total += contentLength;
}
Přidání metody procesu
Přidejte následující ProcessUrlAsync
metodu pod metodu SumPageSizesAsync
:
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;
}
Pro každou danou adresu URL metoda použije client
instanci poskytnutou k získání odpovědi jako byte[]
. Instance CancellationToken se předává do HttpClient.GetAsync(String, CancellationToken) metod a HttpContent.ReadAsByteArrayAsync() metod. Používá se token
k registraci pro požadované zrušení. Délka se vrátí poté, co se adresa URL a délka zapíší do konzoly.
Příklad výstupu aplikace
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.
Kompletní příklad
Následující kód je úplný text souboru Program.cs příkladu.
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;
}
}