Zrušení asynchronních úloh po určité době
Asynchronní operaci můžete po určité době zrušit pomocí CancellationTokenSource.CancelAfter metody, pokud nechcete čekat na dokončení operace. Tato metoda naplánuje zrušení všech přidružených úkolů, které nejsou dokončeny během časového období určeného výrazem CancelAfter
.
Tento příklad přidá do kódu vyvinutého v části Zrušit seznam úkolů (C#) ke stažení seznamu webů a k zobrazení délky obsahu každého z nich.
Tento kurz zahrnuje:
- Aktualizace existující konzolové aplikace .NET
- Naplánování zrušení
Požadavky
V tomto kurzu budete potřebovat následující:
- Očekává se, že jste vytvořili aplikaci v kurzu Zrušení seznamu úkolů (C#).
- .NET 5 nebo novější sada SDK
- Integrované vývojové prostředí (IDE)
Aktualizace vstupního bodu aplikace
Nahraďte existující Main
metodu následujícím kódem:
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.");
}
Aktualizovaná Main
metoda zapisuje do konzoly několik instrukčních zpráv. V rámci try-catch
volání naplánuje CancellationTokenSource.CancelAfter(Int32) zrušení. To bude signalizovat zrušení po určité době.
V dalším kroku se očekává metoda SumPageSizesAsync
. Pokud zpracování všech adres URL proběhne rychleji než plánované zrušení, aplikace skončí. Pokud se však plánované zrušení aktivuje před zpracováním všech adres URL, OperationCanceledException vyvolá se vyvolá.
Příklad výstupu aplikace
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.
Kompletní příklad
Následující kód je úplný text souboru Program.cs pro příklad.
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;
}
}