Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 用异步方法选择_C#_Linq_Async Await - Fatal编程技术网

C# 用异步方法选择

C# 用异步方法选择,c#,linq,async-await,C#,Linq,Async Await,我发现了一个对我来说非常有用的方法,但我仍然不知道LINQ world中的等效方法还有哪些进一步的构造: public async Task<List<ObjectInfo>> GetObjectsInfo(string[] objectIds) { var result = new List<ObjectInfo>(objectIds.Length); foreach (var id in objectIds) { r

我发现了一个对我来说非常有用的方法,但我仍然不知道LINQ world中的等效方法还有哪些进一步的构造:

public async Task<List<ObjectInfo>> GetObjectsInfo(string[] objectIds)
{
    var result = new List<ObjectInfo>(objectIds.Length);
    foreach (var id in objectIds)
    {
        result.Add(await GetObjectInfo(id));
    }

    return result;
}
这些任务不是同时开始的吗? 在我的情况下,最好将它们串联运行

编辑1:回答西奥多·祖利亚斯的评论

当然,我忘记了方法名称中的异步后缀

GetObjectInfo异步方法向外部服务发出http请求。此外,该服务对请求的频率有限制,所以我使用以下结构

            using (var throttler = new Throttler(clientId))
            {
                while (!throttler.IsCallAllowed(out var waitTime))
                {
                    await Task.Delay(waitTime);
                }

                var response = await client.PerformHttpRequestAsync(request);
                return response.Content.FromJson<TResponse>(serializerSettings);
            }

Throttler知道每个客户端的最后一个请求的时间。

在使用Whalll时,应考虑以下因素

如果任何提供的任务在故障状态下完成,则返回的任务也将在故障状态下完成,其中其异常将包含来自每个提供的任务的未包装异常集合

如果提供的任务都没有出现故障,但其中至少有一个已取消,则返回的任务将以取消状态结束

如果没有任何任务出现故障,也没有任何任务被取消,则生成的任务将以RANTO完成状态结束

如果提供的数组/枚举表不包含任务,则返回的任务在返回给调用方之前将立即转换为RanToCompletion状态

这意味着,虽然项目可能会同时运行,但您无法知道如何运行,因为这取决于机器的资源,并且您无法知道顺序,上述情况无法避免


如果您希望对每个案例和特定顺序进行特定的错误处理,那么第一个解决方案就是要走的路。它有点超越了async/await的要点,但不是全部。即使按顺序执行异步项,线程至少不会进入睡眠状态,并且在等待项准备就绪之前仍可使用。

在使用whalll时,您应该考虑以下注意事项

如果任何提供的任务在故障状态下完成,则返回的任务也将在故障状态下完成,其中其异常将包含来自每个提供的任务的未包装异常集合

如果提供的任务都没有出现故障,但其中至少有一个已取消,则返回的任务将以取消状态结束

如果没有任何任务出现故障,也没有任何任务被取消,则生成的任务将以RANTO完成状态结束

如果提供的数组/枚举表不包含任务,则返回的任务在返回给调用方之前将立即转换为RanToCompletion状态

这意味着,虽然项目可能会同时运行,但您无法知道如何运行,因为这取决于机器的资源,并且您无法知道顺序,上述情况无法避免


如果您希望对每个案例和特定顺序进行特定的错误处理,那么第一个解决方案就是要走的路。它有点超越了async/await的要点,但不是全部。即使按顺序执行异步项,您的线程至少不会进入睡眠状态,并且在等待项准备就绪之前仍可使用。

可能的重复:我们只知道将同步创建一组任务。我们可以假设它们将在热状态下创建,换句话说,它们已经开始创建,并且它们的创建速度足够快,可以认为是同步的。但我们需要查看GetObjectInfo的代码才能确定。哪一个BTW应该命名为GetObjectInfo async。因此任务是热的,因为它们是由异步方法创建的。每个任务的创建都涉及到节流器对象的创建,并调用其IsCallAllowed方法。这两种情况都可能造成阻塞。例如,IsCallAllowed可能需要查询数据库。当使用Select方法创建多个这样的任务并将结果枚举传递给Task.WhenAll方法时,这些延迟相加。在这种情况下,说任务同时启动可能并不准确。@TheodorZoulias,幸运的是,此方法访问一个静态ConcurrentDictionary对象。在这种情况下,行wait Task.WhenallObjectId.Selectid=>GetObjectInfo;将几乎同时启动所有任务。可能重复:我们所知道的是,将同步创建一组任务。我们可以假设它们将在热状态下创建,换句话说,它们已经开始创建,并且它们的创建速度足够快,可以认为是同步的。但我们需要查看GetObjectInfo的代码才能确定。哪一个BTW应该命名为GetObjectInfo async。因此任务是热的,因为它们是由异步方法创建的。每个任务的创建都涉及到节流器对象的创建,并调用其IsCallAllowed方法。这两种情况都可能造成阻塞。例如,IsCallAllowed可能需要查询数据库。创建多个
通过使用Select方法并将结果可枚举项传递给Task.whalll方法,这些延迟将相加。在这种情况下,说任务同时启动可能并不准确。@TheodorZoulias,幸运的是,此方法访问一个静态ConcurrentDictionary对象。在这种情况下,行wait Task.WhenallObjectId.Selectid=>GetObjectInfo;将几乎同时启动所有任务。因此,从任务执行的角度来看,在不考虑一致性错误和异常的情况下,foreach的代码块几乎等同于whalll?因为它会在短时间内创建大量任务,这些任务将根据系统调度程序进行处理-就像在WhenAll构造中一样?事实并非如此。带有wait关键字的for语句将按顺序运行任务。因此,如果顺序是不相关的,那么“当一切都好起来时”,因为它会更快地结束。顺序意味着下一个任务将仅在上一次完成后开始?正是这样。task类下没有任何任务。即使是Microsoft文档也有与您几乎相同的示例。您可以在列表中使用for each,但它不会有太大区别。因此,从任务执行的角度来看,在不考虑一致性错误和异常的情况下,使用foreach的代码块几乎等同于使用WhenAll的代码块?因为它会在短时间内创建大量任务,这些任务将根据系统调度程序进行处理-就像在WhenAll构造中一样?事实并非如此。带有wait关键字的for语句将按顺序运行任务。因此,如果顺序是不相关的,那么“当一切都好起来时”,因为它会更快地结束。顺序意味着下一个任务将仅在上一次完成后开始?正是这样。task类下没有任何任务。即使是Microsoft文档也有与您几乎相同的示例。你可以对列表中的每一个都使用一个,但这不会有多大区别。
            using (var throttler = new Throttler(clientId))
            {
                while (!throttler.IsCallAllowed(out var waitTime))
                {
                    await Task.Delay(waitTime);
                }

                var response = await client.PerformHttpRequestAsync(request);
                return response.Content.FromJson<TResponse>(serializerSettings);
            }