windowsC#-在异步任务完成时处理

devtools/2024/11/26 0:20:46/

通过使用 Task.WhenAny,可同时启动多个任务,并在它们完成时逐个对它们进行处理,而不是按照它们的启动顺序进行处理。

下面的示例使用查询来创建一组任务。 每个任务都下载指定网站的内容。 在对 while 循环的每次迭代中,对 WhenAny 的等待调用返回任务集合中首先完成下载的任务。 此任务从集合中删除并进行处理。 循环重复进行,直到集合中不包含任何任务。

创建示例应用程序

创建新的 .NET Core 控制台应用程序。 可使用 dotnet new console 命令或 Visual Studio 进行创建。

在代码编辑器中打开 Program.cs 文件,并将现有代码替换为以下代码:

using System.Diagnostics;namespace ProcessTasksAsTheyFinish;class Program
{static void Main(string[] args){Console.WriteLine("Hello World!");}
}
添加字段

在 Program 类定义中,添加以下两个字段:

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"
};

HttpClient 公开发送 HTTP 请求和接收 HTTP 响应的能力。 s_urlList 包括应用程序计划处理的所有 URL。

更新应用程序入口点

控制台应用程序的主入口点是 Main 方法。 将现有方法替换为以下内容:

static Task Main() => SumPageSizesAsync();

目前将已更新的 Main 方法视为异步 main 方法,这允许将异步入口点引入可执行文件中。 它表示为对 SumPageSizesAsync 的调用。

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

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

static async Task SumPageSizesAsync()
{var stopwatch = Stopwatch.StartNew();IEnumerable<Task<int>> downloadTasksQuery =from url in s_urlListselect ProcessUrlAsync(url, s_client);List<Task<int>> downloadTasks = downloadTasksQuery.ToList();int total = 0;while (downloadTasks.Any()){Task<int> finishedTask = await Task.WhenAny(downloadTasks);downloadTasks.Remove(finishedTask);total += await finishedTask;}stopwatch.Stop();Console.WriteLine($"\nTotal bytes returned:  {total:#,#}");Console.WriteLine($"Elapsed time:          {stopwatch.Elapsed}\n");
}

while 循环将删除每次迭代中的一项任务。 完成各项任务后,循环结束。 该方法从实例化和启动 Stopwatch 开始。 然后它会包含一个查询,执行此查询时,将创建任务集合。 每次对以下代码中的 ProcessUrlAsync 进行调用都会返回 Task<TResult>,其中 TResult 是一个整数:

IEnumerable<Task<int>> downloadTasksQuery =from url in s_urlListselect ProcessUrlAsync(url, s_client);

由于 LINQ 的延迟执行,因此可调用 Enumerable.ToList 来启动每个任务。

List<Task<int>> downloadTasks = downloadTasksQuery.ToList();

while 循环针对集合中的每个任务执行以下步骤:

// 1. 等待调用 WhenAny,以标识集合中首个已完成下载的任务。Task<int> finishedTask = await Task.WhenAny(downloadTasks);// 2. 从集合中移除任务。
downloadTasks.Remove(finishedTask);// 3. 等待 finishedTask,由对 ProcessUrlAsync 的调用返回。 
// finishedTask 变量是 Task<TResult>,其中 TResult 是整数。 
// 任务已完成,但需等待它检索已下载网站的长度,如以下示例所示。 
// 如果任务出错,await 将引发存储在 AggregateException 中的第一个子异常,
// 这一点与读取 Task<TResult>.Result 属性将引发 AggregateException 不同。total += await finishedTask;
添加进程方法

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

static async Task<int> ProcessUrlAsync(string url, HttpClient client)
{byte[] content = await client.GetByteArrayAsync(url);Console.WriteLine($"{url,-60} {content.Length,10:#,#}");return content.Length;
}

对于任何给定的 URL,该方法都将使用提供的 client 实例以 byte[] 形式来获取响应。 将 URL 和长度写入控制台后会返回该长度。

多次运行此程序以验证并不总是以相同顺序显示已下载的长度。

如示例所示,可以在循环中使用 WhenAny 来解决涉及少量任务的问题。 但是,如果要处理大量任务,可以采用其他更高效的方法。

完整示例

下列代码是示例的 Program.cs 文件的完整文本。

using System.Diagnostics;HttpClient s_client = new()
{MaxResponseContentBufferSize = 1_000_000
};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"
};await SumPageSizesAsync();async Task SumPageSizesAsync()
{var stopwatch = Stopwatch.StartNew();IEnumerable<Task<int>> downloadTasksQuery =from url in s_urlListselect ProcessUrlAsync(url, s_client);List<Task<int>> downloadTasks = downloadTasksQuery.ToList();int total = 0;while (downloadTasks.Any()){Task<int> finishedTask = await Task.WhenAny(downloadTasks);downloadTasks.Remove(finishedTask);total += await finishedTask;}stopwatch.Stop();Console.WriteLine($"\nTotal bytes returned:    {total:#,#}");Console.WriteLine($"Elapsed time:              {stopwatch.Elapsed}\n");
}static async Task<int> ProcessUrlAsync(string url, HttpClient client)
{byte[] content = await client.GetByteArrayAsync(url);Console.WriteLine($"{url,-60} {content.Length,10:#,#}");return content.Length;
}// Example output:
// https://learn.microsoft.com                                      132,517
// https://learn.microsoft.com/powershell                            57,375
// https://learn.microsoft.com/gaming                                33,549
// https://learn.microsoft.com/aspnet/core                           88,714
// https://learn.microsoft.com/surface                               39,840
// https://learn.microsoft.com/enterprise-mobility-security          30,903
// https://learn.microsoft.com/microsoft-365                         67,867
// https://learn.microsoft.com/windows                               26,816
// https://learn.microsoft.com/maui                               57,958
// https://learn.microsoft.com/dotnet                                78,706
// https://learn.microsoft.com/graph                                 48,277
// https://learn.microsoft.com/dynamics365                           49,042
// https://learn.microsoft.com/office                                67,867
// https://learn.microsoft.com/system-center                         42,887
// https://learn.microsoft.com/education                             38,636
// https://learn.microsoft.com/azure                                421,663
// https://learn.microsoft.com/visualstudio                          30,925
// https://learn.microsoft.com/sql                                   54,608
// https://learn.microsoft.com/azure/devops                          86,034// Total bytes returned:    1,454,184
// Elapsed time:            00:00:01.1290403

http://www.ppmy.cn/devtools/136974.html

相关文章

前端框架 Redux tool RTK 总结

目录 一、安装依赖 二、创建redux仓库的目录结构 三、createSlice 四、configureStore 五、配置全局仓库标签 六、useSelector 七、useDispatch Redux Tool官网&#xff1a;Redux - A JS library for predictable and maintainable global state management | Redux 一…

gitHub常用操作

gitHub常用操作 1、把项目拉下来2、添加上游仓库3、进入分支4、从上游仓库拉取更新 1、把项目拉下来 在对应项目的右上角点击fork&#xff0c;fork下来&#xff1a;将远程仓库复制到个人仓库 在创建好的分支文件夹下使用 git clone自己远程仓库下的http地址&#xff08;fork…

手机发展史介绍

手机&#xff0c;这个曾经在电影和科幻小说中出现的高科技产品&#xff0c;如今已经渗透进了我们生活的每个角落。从单纯的通讯工具到如今集成了通讯、娱乐、工作、社交等多种功能的智能终端&#xff0c;手机的发展史也是人类科技进步的缩影。本文将从手机的发展历程、技术革新…

在 ARM 平台上如何实现Linux系统的1秒启动

在ARM平台上实现Linux系统的1秒启动&#xff0c;是一项涉及深层次优化的挑战。这不仅需要对系统的各个层面进行精细调整&#xff0c;还需要确保在保持系统稳定性的同时&#xff0c;实现快速启动。以下是实现这一目标的关键步骤和优化工作&#xff1a; 1. 精简U-Boot启动过程 …

MySQL底层概述—1.InnoDB内存结构

大纲 1.InnoDB引擎架构 2.Buffer Pool 3.Page管理机制之Page页分类 4.Page管理机制之Page页管理 5.Change Buffer 6.Log Buffer 1.InnoDB引擎架构 (1)InnoDB引擎架构图 (2)InnoDB内存结构 (1)InnoDB引擎架构图 下面是InnoDB引擎架构图&#xff0c;主要分为内存结构和磁…

LLM: AI Mathematical Olympiad (下)

文章目录 一、SC-TIR策略&#xff08;工具整合推理&#xff09;二、SC-TIR原理三、避免过拟合四、代码分析1、Main函数2、SC-TIR control flow3、Extract answer4、Execute completion 总结 本文较长分成两个部分分析 | ू•ૅω•́)ᵎᵎᵎ 第一部分&#xff1a;预备知识介绍和…

k8s 对外服务之 Ingress

LB ingress //Ingress 简介 service的作用体现在两个方面&#xff0c;对集群内部&#xff0c;它不断跟踪pod的变化&#xff0c;更新endpoint中对应pod的对象&#xff0c;提供了ip不断变化的pod的服务发现机制&#xff1b;对集群外部&#xff0c;他类似负载均衡器&#xff0c;…

【SKFramework框架】一、框架介绍

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享QQ群&#xff1a;398291828小红书小破站 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 【Unity3D框架】SKFramework框架完全教程《全…