我有以下示例代码:

    private async Task<IEnumerable<long>> GetValidIds1(long[] ids)
    {
        var validIds = new List<long>();
        var results = await Task.WhenAll(ids.Select(i => CheckValidIdAsync(i)))
            .ConfigureAwait(false);
        for (int i = 0; i < ids.Length; i++)
        {
            if (results[i])
            {
                validIds.Add(ids[i]);
            }
        }
        return validIds;
    }

    private async Task<IEnumerable<long>> GetValidIds2(long[] ids)
    {
        var validIds = new ConcurrentBag<long>();
        await Task.WhenAll(ids.Select(async i =>
        {
            var valid = await CheckValidIdAsync(i);
            if (valid)
                validIds.Add(i);
        })).ConfigureAwait(false);
        return validIds;
    }

    private async Task<bool> CheckValidIdAsync(long id);

我目前使用的是GetValidIds1(),但它的不便之处在于必须将输入ID与最后使用index的结果绑定在一起.

GetValidIds2()是我想要编写的内容,但有几个问题:

  1. 我在SELECT lambda表达式中有‘Await’.因为LINQ是延迟计算,我认为它不会阻止其他CheckValidIdAsync()个调用的启动,但它究竟挂起了谁的上下文?每个MSDN文档

等待运算符挂起封闭的异步方法的计算,直到其操作数表示的异步操作完成.

那么,在本例中,封闭的异步方法本身就是lambda表达式,所以它不会影响其他调用?

  1. 有没有更好的方法来处理异步方法的结果并将该过程的输出收集到列表中?

推荐答案

另一种方法是将每个long ID投影到Task<ValueTuple<long, bool>>,而不是将其投影到Task<bool>.这样,您将能够使用纯LINQ过滤结果:

private async Task<long[]> GetValidIds3(long[] ids)
{
    IEnumerable<Task<(long Id, bool IsValid)>> tasks = ids
        .Select(async id =>
        {
            bool isValid = await CheckValidIdAsync(id).ConfigureAwait(false);
            return (id, isValid);
        });
    var results = await Task.WhenAll(tasks).ConfigureAwait(false);
    return results
        .Where(e => e.IsValid)
        .Select(e => e.Id)
        .ToArray();
}

以上GetValidIds3项与你问题中的GetValidIds1项相同.它以与原始ids相同的顺序返回过滤后的ID.相反,GetValidIds2并不能保证任何订单.如果必须使用并发集合,则it's better将使用ConcurrentQueue<T>而不是ConcurrentBag<T>,因为前者保留了插入顺序.即使顺序并不重要,保留它也会使调试变得更容易.

Csharp相关问答推荐

ß != ss与ICU进行不区分大小写的比较

System.Data.SQLite:判断SQLite数据库是否为空(任何表中至少有一行)

向类注入一个工厂来创建一些资源是一个好的实践吗?

. NET在上一个操作完成之前,在此上下文实例上启动了第二个操作

System.Text.Json数据化的C#类映射

. NET 8控制台应用程序DI错误无法解析Microsoft. Extension. Logging. ILoggerFactory类型的服务'''

实体框架核心上是否支持使用NPGSQL的字符串聚合?

XUNIT是否使用测试数据的源生成器?

应用程序重新启动后,EFCore列表的BSON反序列化错误

如何将MongoDB序列化程序设置为内部对象属性

如何使用MoQ模拟Resources GroupCollection?

如何在C#中创建VS代码中的控制台应用程序时自动生成Main方法

如何将DotNet Watch与发布配置和传递给应用程序的参数一起使用?

在C#中,非静态接口方法的抽象和虚拟是冗余的吗?

交替的奇数

Visual Studio 17.8.0制表符自动完成问题--三缩进

为什么连接到Google OAuth2后,结果.Credential为空?

将文本从剪贴板粘贴到RichTextBox时,新文本不会在RichTextBox ForeColor中着色

在C#中删除多个不同名称的会话

缩写的MonthNames有问题