Annullare attività asincrone dopo un periodo di tempo
È possibile annullare un'operazione asincrona dopo un periodo di tempo tramite il metodo CancellationTokenSource.CancelAfter se non si vuole attendere fino al completamento dell'operazione. Questo metodo pianifica l'annullamento di qualsiasi attività associata che non è stata completata nel periodo di tempo designato dall'espressione CancelAfter
.
Questo esempio viene aggiunto al codice sviluppato in Annullare un elenco di attività (C#) per scaricare un elenco di siti Web e per visualizzare la lunghezza del contenuto di ogni sito.
Contenuto dell'esercitazione:
- Aggiornamento di un'applicazione console .NET esistente
- Pianificazione di un annullamento
Prerequisiti
Per completare questa esercitazione, è necessario disporre di:
- È prevista la creazione di un'applicazione nell'esercitazione Annullare un elenco di attività (C#)
- .NET 5 o versione successiva dell'SDK
- Ambiente di sviluppo integrato (IDE)
Aggiornare il punto di ingresso dell'applicazione
Sostituire il metodo Main
esistente con quanto segue:
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.");
}
Il metodo aggiornato Main
scrive alcuni messaggi di istruzioni nella console. All'interno di try-catch
, una chiamata a CancellationTokenSource.CancelAfter(Int32) pianifica un annullamento. Questo segnalerà l'annullamento dopo un periodo di tempo.
Successivamente, resta in attesa il metodo SumPageSizesAsync
. Se l'elaborazione di tutti gli URL si verifica più velocemente dell'annullamento pianificato, l'applicazione termina. Tuttavia, se l'annullamento pianificato viene attivato prima dell'elaborazione di tutti gli URL, viene generata un'eccezione OperationCanceledException.
Output dell'applicazione di esempio
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.
Esempio completo
Il codice seguente è il testo completo del file Program.cs per l'esempio.
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;
}
}