当前位置: 代码网 > it编程>编程语言>C# > C# - 能否让 SortedSet.RemoveWhere 内传入的委托异步执行

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

2024年05月12日 C# 我要评论
若想充分利用 `RemoveWhere` 带来的性能优势,建议传入判断是否删除元素的委托内采取同步操作。若一定要在该委托内使用异步操作,可以采用本文中绕行的方法,但摈弃了 `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 的顺序,按序遍历。
  • 最后,这种方法在异步评估谓词时仍然会在遍历每个元素时阻塞,因为我们需要等待每个异步谓词的完成。如果你需要更高效的异步处理,你可能需要考虑使用其他数据结构或并行处理技术。
(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com