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 ...
随机推荐
- linux xfce 在文件管理器里点击运行shell脚本文件
1.打开 Settings Editor 2.点击左边的 thunar 3.点击右边的 添加 ,在属性中输入 /misc-exec-shell-scripts-by-default 在类型中选择布尔类 ...
- zookeeper集群启动脚本文件
cd bin/ vim myzk.sh for host in hadoop102 hadoop103 hadoop104 do ssh $host "source /etc/profile ...
- python---nltk工具包安装
先在pycharm里安装nltk cmd进入Python输入 import nltk nltk.download()如果下载失败在github上下载语料库:https://github.com/nlt ...
- C语言跨平台时间操作计算时间差
头文件 #pragma once #if defined(_WIN32) #include<sys/timeb.h> #if defined(__UNIX__)||defined(__AP ...
- 19 JavaScript的hook
19 JavaScript的hook 什么叫hook? Hook技术又叫钩子函数,在系统没有调用该函数之前,钩子程序就捕获该消息,钩子函数先得到该函数的控制权,这时钩子函数既可以改变该函数的执行行为, ...
- #状压dp,拓扑排序,内向基环树#CF1242C Sum Balance
题目 有 \(k\) 个盒子, 第 \(i\) 个盒子有 \(n_i\) 个数. 保证所有数互不相同. 从每个盒子各拿出一个数, 并按照某种顺序放回去(每个盒子恰好放入一个数). 判断是否能使操作后所 ...
- #dp#洛谷 4399 [JSOI2008]Blue Mary的职员分配
题目 分析 设\(dp[i][day][j][k]\)表示当前雇员个数为\(i\), 距离上次发广告时间为\(day\),获得的金钱和声望分别为\(j,k\) 注意\(day\)是\([0\sim 3 ...
- 2款Notepad++平替工具(实用、跨平台的文本编辑器)
前言 今天大姚给大家分享2款Notepad++平替工具,实用.跨平台(支持Window/MacOS/Linux操作系统平台)的文本编辑器. NotepadNext NotepadNext是一个跨平台的 ...
- 微信小程序为什么引入 rpx
前言 众所周知,px 是一个叫做像素的东西,pixel. 像素是指由图像的小方格组成的,这些小方块都有一个明确的位置和被分配的色彩数值,小方格颜色和位置就决定该图像所呈现出来的样子. 可以将像素视为整 ...
- ef 查询生成语句的几种方式
前言 整理一下ef 如何查看生成sql 语句的,现在有ef core 了,统一整理一下. 正文 方式如下: 数据库监听 这是一种推荐方式,因为调试和代码分开,不会有影响. 然后连接: 然后可以进行一些 ...