在一段時間後取消非同步工作
如果不想等候作業完成,則可以使用 CancellationTokenSource.CancelAfter 方法,在一段時間之後取消非同步作業。 此方法會排程取消未在 CancelAfter
運算式所指定之期間內完成的任何相關工作。
此範例會新增至取消工作清單 (C#) 中所開發的程式碼來下載網站清單,以及顯示每個網站內容的長度。
此教學課程涵蓋:
- 更新現有的 .NET 主控台應用程式
- 排程取消
必要條件
本教學課程需要下列:
- 您應該已在取消工作清單 (C#) 教學課程中建立應用程式
- .NET 5 或更新版本的 SDK
- 整合式開發環境 (IDE)
更新應用程式進入點
將現有的 Main
方法取代為以下內容:
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.");
}
更新的 Main
方法會將一些指示訊息寫入主控台。 在 try-catch
中,CancellationTokenSource.CancelAfter(Int32) 的呼叫會排程取消。 這會在一段時間後發出取消訊號。
接著,SumPageSizesAsync
方法會進入等待。 如果處理所有 URL 的速度比排程取消更快,應用程式就會結束。 不過,如果在處理所有 URL 之前觸發排程取消,則會擲回 OperationCanceledException。
範例應用程式輸出
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.
完整範例
下列程式碼是範例 Program.cs 檔案的完整文字。
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;
}
}