C# - 能否让 SortedSet.RemoveWhere 内传入的委托异步执行

这篇具有很好参考价值的文章主要介绍了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 中删除收集到的元素。

请注意:文章来源地址https://www.toymoban.com/news/detail-858744.html

  • 首先,这种方法在异步评估谓词后引入了一个同步阶段(在删除元素时),在数据量较大的情况下不可避免地增加一定的性能开销。
  • 其次,SortedSet 自带的同步方法 RemoveWhere 不在意 Enumerator 的顺序,执行一个广度优先的从左到右的遍历,相较 Enumerator 的遍历效率更高(参考链接),而我们这里的异步方法 RemoveWhereAsync 并没有这类的优化算法,简单地使用 foreach 按照 Enumerator 的顺序,按序遍历。
  • 最后,这种方法在异步评估谓词时仍然会在遍历每个元素时阻塞,因为我们需要等待每个异步谓词的完成。如果你需要更高效的异步处理,你可能需要考虑使用其他数据结构或并行处理技术。

到了这里,关于C# - 能否让 SortedSet.RemoveWhere 内传入的委托异步执行的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C# 常量 结构体 委托

    常量名命名一般使用大写字母 开发一个游戏,游戏角色有法师(Mage)、射手(Archer)、刺客(Assassin)、坦克(Tank)、铺助(Support)、战士(Warrior),等不同类型。 ❓如何存储游戏角色 使用 int 类型 :创建一套规则,提前为各个类型角色绑定一个数字标识 使用枚举类型 什么是枚举类型?

    2024年02月02日
    浏览(33)
  • c#委托详解

    委托是一种能够将方法作为参数传递、存储方法并且调用方法的类型,它可以让我们写出更加灵活和可扩展的代码。委托通常用于回调 (Callback) 机制,比如在事件处理、异步编程、LINQ 查询等场景中常常会使用委托。它可以将方法作为参数传递给其他方法,从而在需要的时候

    2023年04月08日
    浏览(29)
  • C#基础--委托

    C#基础–委托 简单说它就是一个能把方法当参数传递的对象,而且还知道怎么调用这个方法,同时也是粒度更小的“接口”(约束了指向方法的签名) 跟方法有点类似,有参数,返回值,访问修饰符+ delegate 委托的本质是一个类,继承自一个特殊类 MulticastDelegate ,我们自己在

    2024年02月16日
    浏览(42)
  • C#之委托

    目录 一、简介 (一)概述 (二)类与委托 二、声明委托 三、使用委托 (一)创建委托对象 (二)使用委托 四、简单的委托示例 五、Action[T]和Func[T]委托 六、多播委托 七、匿名方法         委托时寻址方法的.NET版本。在C++中,函数指针只不过是一个指向内存位置的指

    2024年01月18日
    浏览(36)
  • C#——委托

    什么是委托        C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。 声明委托          委托声明决定了可由该委托引用的方法。委托可指向一个与其具有相同标签的方法。  

    2023年04月15日
    浏览(29)
  • c# 事件与委托

    //在C#中, 事件是一种特殊的委托 ,它允许对象通知其他对象发生了某个特定的事件。 //事件通常用于GUI应用程序中,例如当用户单击按钮时,按钮控件会引发Click事件, //然后其他对象可以订阅该事件并执行相应的操作。 //以下是一个简单的示例,演示如何在C#中使用事件和

    2024年02月06日
    浏览(39)
  • C#编程-实现委托

    委托是可以存储对方法的引用的对象。在C#中,委托允许您动态地改变类中方法的引用。 考虑咖啡售货机的示例,它配置不同口味的咖啡,例如卡布奇诺咖啡和黑咖啡。在选择所需口味的咖啡时,售货机决定混合各种成分,例如奶粉、咖啡粉、热水、卡布奇诺咖啡粉。所有的

    2024年02月02日
    浏览(36)
  • Unity学前C#:委托详解

    字面意思就是:这件事情我不亲自去做,而是委托别人去做 C#中的委托有点类似c/c++中的函数指针,但是C#中的委托就可以看作是函数指针的升级版 以下是c/c++的函数指针实例  先理解一个概念: 一切皆地址 在计算机中所有的程序以及数据的存储都是有地址可循的,计算机组成原理

    2024年03月19日
    浏览(44)
  • 委托与事件(一)——C#版本

      委托是对 函数的封装 ,可以当作给方法的特征指定一个名称。而事件则是 委托的一种特殊形式 ,当发生有意义的事情时,事件对象处理通知过程。   委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有 完全相同的行为 。   用例子来说明为

    2023年04月09日
    浏览(43)
  • C#匿名方法增加、删除委托

    匿名方法给我们带来了方便,那么如何增加删除匿名方法中附加的委托(事件)呢 一般写法: 1 2 3 4 this .Loaded += (sender, e) =       {              //Do something       }; 进化写法: 1 2 3 4 5 6 7 this .Loaded += new   RoutedEventHandler(FormulaAssign_Loaded); void   FormulaAssign_Loaded( objec

    2024年02月11日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包