如果不想等待异步控制台应用程序完成,可以取消该应用程序。 通过遵循本文的示例,可将取消添加到下载网站内容的应用程序。 可通过将 CancellationTokenSource 实例与每个任务进行关联来取消多个任务。 如果选择 Enter 键,则将取消所有尚未完成的任务。
创建示例应用程序
创建新的 .NET Core 控制台应用程序。 可通过使用 dotnet new console 命令或从 Visual Studio 进行创建。 在你最喜欢的编辑器中打开 Program.cs 文件。
替换 using 语句
将现有 using 语句替换为以下声明:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
添加字段
在 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"
};
CancellationTokenSource 用于向 CancellationToken 发出请求取消的信号。 HttpClient 公开发送 HTTP 请求和接收 HTTP 响应的能力。 s_urlList 包括应用程序计划处理的所有 URL。
更新应用程序入口点
控制台应用程序的主入口点是 Main 方法。 将现有方法替换为以下内容:
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.");
}
目前将已更新的 Main 方法视为异步 main 方法,这允许将异步入口点引入可执行文件中。 将几条说明性消息写入控制台,然后声明名为 cancelTask 的 Task 实例,这将读取控制台密钥笔画。 如果按 Enter,则会调用 CancellationTokenSource.Cancel()。 这将发出取消信号。 下一步,从 SumPageSizesAsync 方法分配 sumPageSizesTask 变量。 然后,将这两个任务传递到 Task.WhenAny(Task[]),这会在完成两个任务中的任意一个时继续。
下一个代码块可确保在取消得到处理之前不会退出应用程序。 如果要完成的第一个任务是 cancelTask,则等待 sumPageSizeTask。 如果已取消,则等待时会引发 System.Threading.Tasks.TaskCanceledException。 块捕获该异常,并输出消息。