Anulowanie zadań asynchronicznych po upływie czasu
Możesz anulować operację asynchroniczną po upływie określonego czasu przy użyciu CancellationTokenSource.CancelAfter metody , jeśli nie chcesz czekać na zakończenie operacji. Ta metoda planuje anulowanie wszelkich skojarzonych zadań, które nie są wykonywane w okresie wyznaczonym przez CancelAfter
wyrażenie.
W tym przykładzie dodamy kod opracowany w sekcji Anuluj listę zadań (C#), aby pobrać listę witryn internetowych i wyświetlić długość zawartości każdego z nich.
W tym samouczku opisano następujące czynności:
- Aktualizowanie istniejącej aplikacji konsolowej .NET
- Planowanie anulowania
Wymagania wstępne
Dla tego samouczka wymagane są następujące elementy:
- Oczekuje się, że aplikacja została utworzona w samouczku Anulowanie listy zadań (C#)
- Zestaw SDK platformy .NET 5 lub nowszej
- Zintegrowane środowisko projektowe (IDE)
Aktualizowanie punktu wejścia aplikacji
Zastąp istniejącą Main
metodę następującym kodem:
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.");
}
Zaktualizowana Main
metoda zapisuje kilka komunikatów instruktażowych w konsoli programu . W programie try-catch
wywołanie w celu CancellationTokenSource.CancelAfter(Int32) zaplanowania anulowania. Spowoduje to zasygnalizację anulowania po upływie określonego czasu.
Następnie oczekiwana SumPageSizesAsync
jest metoda . Jeśli przetwarzanie wszystkich adresów URL odbywa się szybciej niż zaplanowane anulowanie, aplikacja kończy się. Jeśli jednak zaplanowane anulowanie zostanie wyzwolone przed przetworzeniem wszystkich adresów URL, OperationCanceledException zostanie zwrócony błąd.
Przykładowe dane wyjściowe aplikacji
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.
Kompletny przykład
Poniższy kod jest kompletnym tekstem pliku Program.cs w tym przykładzie.
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;
}
}