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 ...
随机推荐
- 记录--通过手写,分析Promise核心原理
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 1. 定义整体结构 先写出构造函数,将Promise向外暴露 /* 自定义Promise函数模块:IIFE */ (function (w ...
- SpringBoot如何优雅的进行参数校验
写在前面 上一篇文章中我们学会了如何优雅的接收前端参数,传送门 SpringBoot如何优雅的接收前端参数 接收到参数后,接下来要做的就是校验参数的合法性.这一步的重要性就不用多说了. 即使前端已经对 ...
- #FFT#P4173 残缺的字符串
题目 有一个长度为 \(m\) 的字符串 \(A\) 和 一个长度为 \(n\) 的字符串 \(B\), 它们有若干位置为通配符,现在问 \(B\) 的每一个后缀是否存在前缀为 \(A\). 分析 考 ...
- OpenHarmony技术日探讨教育发展,聚焦开源人才培养
4 月 25 日,OpenAtom OpenHarmony (以下简称"OpenHarmony")技术日在深圳成功举办.作为 OpenHarmony 开源项目的年度盛会,大会以&q ...
- SQline安装
SQLite 安装 SQLite 的一个重要的特性是零配置的,这意味着不需要复杂的安装或管理.本章将讲解 Windows.Linux 和 Mac OS X 上的安装设置. 在 Windows 上安装 ...
- VSCode如何通过Ctrl+P快速打开node_modules中的文件
背景 咱们新建一个NodeJS项目,必然会安装许多依赖包,因此经常需要查阅某些依赖包的源码文件.但是,由于node_modules目录包含的文件太多,出于性能考虑,在VSCode中默认情况下是禁止搜索 ...
- VScode 使用emmet
背景 在很多的编辑场合,很多时候回出现很多逻辑性的问题.可能觉得html是一门没有逻辑的语言,实际上,它是有一定的思想编辑的.后来出现了emmet,这个不仅仅是一种快捷方式,同时也是一种思考方式. 解 ...
- Pytorch-tensor的感知机,链式法则
1.单层感知机 单层感知机的主要步骤: 1.对数据进行一个权重的累加求和,求得∑ 2.将∑经过一个激活函数Sigmoid,得出值O 3.再将O,经过一个损失函数mse_loss,得出值loss 4.根 ...
- pypinyin 获取拼音,作为智能设备的唤醒比对结果
from pypinyin import lazy_pinyin,TONE,TONE2,TONE3,NORMAL a = "小七同学" b = "小琦同学" c ...
- ASP.NET CORE 框架揭秘读书笔记系列——命令行程序的创建(一)
一.dotnet --info 查看本机开发环境 dotnet --info 会显示本机安装的SDK版本.运行时环境.运行时版本 二.利用命令行创建.NET项目 我们不仅可以利用脚手架模版创建各种类 ...