windows C#-取消任务列表(下)

创建异步总和页面大小方法

在 Main 方法下,添加 SumPageSizesAsync 方法:

复制代码
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");
}

该方法从实例化和启动 Stopwatch 开始。 然后会在 s_urlList 的每个 URL 中进行循环,并调用 ProcessUrlAsync。 对于每次迭代,s_cts.Token 都会传递到 ProcessUrlAsync 方法中,并且代码将返回 Task<TResult>,其中 TResult 是一个整数:

复制代码
int total = 0;
foreach (string url in s_urlList)
{
    int contentLength = await ProcessUrlAsync(url, s_client, s_cts.Token);
    total += contentLength;
}
添加进程方法

在 SumPageSizesAsync 方法下添加以下 ProcessUrlAsync 方法:

复制代码
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;
}

对于任何给定的 URL,该方法都将使用提供的 client 实例以 byte\[\] 形式来获取响应。 CancellationToken 实例会传递到 HttpClient.GetAsync(String, CancellationToken) 和 HttpContent.ReadAsByteArrayAsync() 方法中。 token 用于注册请求取消。 将 URL 和长度写入控制台后会返回该长度。

示例应用程序输出
复制代码
Application started.
Press the ENTER key to cancel...

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
https://learn.microsoft.com/dotnet                                67,452
https://learn.microsoft.com/dynamics365                           48,582
https://learn.microsoft.com/education                             22,924

ENTER key pressed: cancelling downloads.

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.");
        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 (OperationCanceledException)
            {
                Console.WriteLine("Download task has been cancelled.");
            }
        }

        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;
    }
}
相关推荐
Funlang18 小时前
在 Windows 95 上跑 Fun
windows
暴走约伯19 小时前
【VFX工具链源码拆解 09】终极工业化闭环:基于 ID 规则驱动的全自动场景建档、骨骼挂载与男转女场景迁移
unity·c#·游戏引擎·材质
ö Constancy1 天前
一台电脑的硬件组成与作用:按功能分类详解(Windows 与 Linux 视角)
linux·windows·电脑
用户788477316342 天前
WinForms 迁移 WPF:Upgrade Assistant 覆盖 30%,剩下 70% 我手写了六周
c#
寂寞的船2 天前
【Unity知识速递】第13期 Unity 内存泄漏排查实战:从 Memory Profiler 到 Lua 引用泄漏的生产级全链路诊断
unity·junit·c#·游戏引擎·lua
雪落漂泊2 天前
Liunux进程(七):程序控制篇(中)
linux·运维·windows
用户3721574261353 天前
C# 提取 PDF 附件:包括文档附件和页面注释附件
c#
寂寞的船3 天前
【Unity Bug挑战】第12期 Awaitable 二次 await 死锁之谜 —— 为什么同一个异步操作等两次就卡死?
unity·c#·游戏引擎·bug
承渊政道3 天前
Fooocus本地AI绘图教程:Windows部署、低门槛生图与远程访问
人工智能·windows·cpolar·fooocus·生图
陈工大模型3 天前
收到乱码压缩包之后,我重新测了 7-Zip、Bandizip 和win解压缩
windows·电脑·软件工程·软件需求·7-zip