C# - 能否让 SortedSet.RemoveWhere 内传入的委托异步执行
TL;DR;
若想充分利用 RemoveWhere 带来的性能优势,建议传入判断是否删除元素的委托内采取同步操作。若一定要在该委托内使用异步操作,可以采用本文中绕行的方法,但摈弃了 RemoveWhere 所带来的性能优势。
正文
(本文由 GPT 辅助撰写)
在.NET中,SortedSet<T> 上的 RemoveWhere 方法本身不支持异步谓词,因为它期望的是一个返回布尔值的同步委托。然而,你可以通过在谓词中使用异步代码来绕过这个限制,使得方法能够在移除元素过程中执行某项异步操作。但在返回结果之前,你需要等待异步操作完成。
下面是一个例子,其中谓词本身是异步的,并在一个同步方法中被等待:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var sortedSet = new SortedSet<int> { 1, 2, 3, 4, 5 };
Console.WriteLine("RemoveWhere 前: " + string.Join(", ", sortedSet));
// 异步移除 SortedSet 内的偶数
int removedCount = await sortedSet.RemoveWhereAsync(IsEvenNumberAsync, CancellationToken.None);
Console.WriteLine("移除了 " + removedCount + " 个元素");
Console.WriteLine("RemoveWhere 后: " + string.Join(", ", sortedSet));
}
static async ValueTask<bool> IsEvenNumberAsync(int element, CancellationToken token)
{
// 模拟一个异步操作,例如网络请求或数据库查询
await Task.Delay(1000, token);
return num % 2 == 0; // 返回一个布尔值,表示是否应该移除该元素
}
}
public static class SortedSetExtension
{
public static async ValueTask<int> RemoveWhereAsync<T>(this SortedSet<T> sortedSet,
Func<T, CancellationToken, ValueTask<bool>> asyncPredicate, CancellationToken token)
{
ArgumentNullException.ThrowIfNull(asyncPredicate);
token.ThrowIfCancellationRequested();
// 由于 SortedSet 不支持遍历过程中移除其中的元素,创建一个等待移除列表来避免 Enumerator 报错
var elementsToRemove = new List<T>(sortedSet.Count);
// 异步地评估谓词
foreach (var element in sortedSet)
{
if (await asyncPredicate(element, token)) // 等待异步操作完成
{
elementsToRemove.Add(element); // 如果应该移除,则添加该元素到等待移除中
}
}
// 同步地移除元素
int actuallyRemoved = 0;
foreach (var element in elementsToRemove)
{
if (sortedSet.Remove(element))
{
actuallyRemoved++;
}
}
return actuallyRemoved;
}
}
在这个例子中:
IsEvenNumberAsync方法模拟了一个异步操作。RemoveWhereAsync方法接收一个异步谓词,并对其进行评估,针对SortedSet中的每个元素。- 在循环内部等待异步谓词的结果。
- 将要删除的元素收集到一个单独的列表中。
- 在评估所有元素之后,将从
SortedSet中删除收集到的元素。
请注意:
- 首先,这种方法在异步评估谓词后引入了一个同步阶段(在删除元素时),在数据量较大的情况下不可避免地增加一定的性能开销。
- 其次,
SortedSet自带的同步方法RemoveWhere不在意Enumerator的顺序,执行一个广度优先的从左到右的遍历,相较Enumerator的遍历效率更高(参考链接),而我们这里的异步方法RemoveWhereAsync并没有这类的优化算法,简单地使用foreach按照Enumerator的顺序,按序遍历。 - 最后,这种方法在异步评估谓词时仍然会在遍历每个元素时阻塞,因为我们需要等待每个异步谓词的完成。如果你需要更高效的异步处理,你可能需要考虑使用其他数据结构或并行处理技术。
C# - 能否让 SortedSet.RemoveWhere 内传入的委托异步执行的更多相关文章
- 关于Kettle的事务和转换内步骤的顺序执行
关于Kettle的事务和转换内步骤的顺序执行 近来有项目中遇到Kettle事务处理和转换内步骤顺序执行的问题.为此进行了研究,找到了一个解决办法. 在Kettle中,一个Job内的转换,缺省是顺序执行 ...
- [日期工具分享][Shell]为特定命令依次传入顺序日期执行
[日期工具分享][Shell]为特定命令依次传入顺序日期执行 使用方式: <本脚本文件名(必要时需要全路径)> <要执行的命令所在的文件名> <开始日期> < ...
- 一键帮你复制多个文件到多个机器——PowerShell小脚本(内附PS远程执行命令问题解析)
作为一个后台程序猿,经常需要把一堆程序集(DLL)或者应用程序(EXE)复制到多个服务器上,实现程序的代码逻辑更新,用以测试新的功能或改动逻辑.这里给大家介绍一个自己实现的PowerShell脚本,方 ...
- JSP第四篇【EL表达式介绍、获取各类数据、11个内置对象、执行运算、回显数据、自定义函数、fn方法库】
什么是EL表达式? 表达式语言(Expression Language,EL),EL表达式是用"${}"括起来的脚本,用来更方便的读取对象! EL表达式主要用来读取数据,进行内容的 ...
- C#使用进程调用bash,不断往bash内插入命令并执行
呃呃呃,遇到了一个非常恶心得问题,现在就是,有几十万条数据需要当作参数调用python脚本 一次一次输入命令过去缓慢,经过了多层考虑决定使用进程来解决(不知道线程怎么开启bash得) 原理非常简单,类 ...
- C#实现简单的委托异步调用
delegate void textAsy(); static void Main(string[] args) { textAsy t = texts; AsyncCallback callBack ...
- JavaScript使用浏览器内置XMLHttpRequest对象执行Ajax请求
所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject).XMLHttpRequest 用于在后台与服务器交换数据.这意味着可以在不重新加载整个 ...
- 关于always块内for循环的执行方式
//该模块主要用来说明for结构在时序逻辑中的执行方式 :] eq_dly ); integer i; 'b1; always @(posedge clk_1 or negedge nrst) beg ...
- Jquery 循环内间隔执行 异步执行
<script type="text/javascript"> var arr = new Array(); var arrk = 0; jQuery(function ...
- (testng多个class文件执行时混乱,不是等一个class内的所有methods执行完再去执行下一个class内的内容)问题的解决
问题描述如下: We use TestNG and Selenium WebDriver to test our web application. Now our problem is that we ...
随机推荐
- Excel多列求平均值
数据源如下所示 需求描述:现在需要根据水果名称和月份求出对应水果的平均单价 一.添加一列辅助列(=A2&B2) 二.Ctrl+A选择所有数据插入数据透视表,选择辅助列到行,客单价到值(值字段设 ...
- gRPC入门学习之旅(三)
gRPC入门学习之旅(一) gRPC入门学习之旅(二) 2.3.创建自定义服务 除上面的模板中自带的一个gRPC服务之后,我们再创建一个自己的服务,我将创建一个用户信息gRPC服务,主要功能有三个,登 ...
- iptables-save 命令使用总结
转载请注明出处: iptables-save 命令在 Linux 系统中用于将当前运行的 iptables 防火墙规则导出到一个文件中.这对于备份规则.迁移规则或在不同系统间共享规则配置非常有用. 基 ...
- spring boot @Scheduled 单线程的问题
package com.lxw.lxwDemo; import org.springframework.scheduling.annotation.EnableScheduling; import o ...
- 一款比Typora更简洁优雅的Markdown编辑器神器(完全开源免费)
前言 自从Typora收费以后经常有朋友会问有没有一个好用.简洁.免费的Markdown编辑器推荐的,今天大姚给大家分享一款比Typora更简洁优雅的.完全开源免费(MIT License)Markd ...
- #插头dp#洛谷 5074 HDU 1693 Eat the Trees
题目 给出 \(n*m\) 的方格,有些格子不能铺线, 其它格子必须铺,可以形成多个闭合回路. 问有多少种铺法? \(n,m\leq 12\) 分析 设 \(dp[n][m][S][0/1]\) 表示 ...
- #dp#nssl 1478 题
分析 设\(f[i]\)表示第\(i\)个是否幸存,\(dp[i][j]\)表示若第\(i\)个幸存,第\(j\)个是否必死 倒序枚举人,如果存在\(dp[i][a[x]],dp[i][b[x]]\) ...
- #树链剖分,LCA#洛谷 3398 仓鼠找sugar
题目 多次询问求树上的两条路径是否有公共点 分析 有公共点当且仅当一条路径的LCA在另一条路径上, 否则一定会形成一个环,那树剖求LCA判断一下LCA是否在另一条路径上即可 代码 #include & ...
- 2、androidStudio调用Unity方法
1.导入Unity的Classes.jar文件 (1).首先找到这个包在哪 Unity版本为5.0之前时,classes.jar的路径: unity的安装路径\Editor\Data\Playback ...
- HDC2021技术分论坛:跨端分布式计算技术初探
作者:zhengkai,分布式通信首席技术专家 当今的移动应用都向着智能化和多样化方向发展,例如AI辅助,VR/AR应用,沉浸式游戏等.然而现实中的移动设备,因为便携性要求受限于尺寸.电池容量以及温控 ...