发送几个异步API请求并并行处理响应的正确方法是什么?

丹尼·马扎雷(Dani Mazahreh)

我有一个项目列表,对于每个项目,我需要执行几个异步API请求并处理响应,我已经看到了几个实现,并且在执行时间上它们都是相似的,但是我想知道它们之间的区别。

方法1

Parallel.ForEach(items, new ParallelOptions { MaxDegreeOfParallelism = 10 }, item =>
        {
            var response = item.propertyOne.GetAsync().GetAwaiter().GetResult();
            //process it
            var response = item.propertyTwo.GetAsync().GetAwaiter().GetResult();
            //process it
            var response = item.propertyThree.GetAsync().GetAwaiter().GetResult();
            //process it
        });

方法2

Parallel.ForEach(items, new ParallelOptions { MaxDegreeOfParallelism = 10 }, item =>
        {
            Task.Run(async () =>
            {
                var response = await item.propertyOne.GetAsync();
            }).GetAwaiter().GetResult();
            //process it
            Task.Run(async () =>
            {
                var response = await item.propertyTwo.GetAsync();
            }).GetAwaiter().GetResult();
            //process it
            Task.Run(async () =>
            {
                var response = await item.propertyThreee.GetAsync();
            }).GetAwaiter().GetResult();
            //process it
        });

方法3假定应用了某种限制机制,以免系统充斥任务

List<Task> tasksToAwait = new List<Task>();
        foreach (var item in items)
        {
            tasksToAwait.Add(Task.Run(async () =>
            {
                var response = await item.propertyOne.GetAsync();
                //process it
                var response = await item.propertyTwo.GetAsync();
                //process it
                var response = await item.propertyThree.GetAsync();
                //process it
            }));
        }
        await Task.WhenAll(taskToAwait);

笔记:

  • 我正在使用GetAwaiter()。GetResult()而不是Wait(),因为它不会吞下异常。
  • 必须以某种方式等待请求才能处理响应。
  • 这是作为后台任务执行的,所以我不介意阻塞调用线程。
  • 第三种方法比其他两种方法略快,第二种方法比第一种略快。
  • 我无法控制通过GetAsync()调用的异步API。

建议使用其中哪一项?如果没有,则建议什么?而且,它们有何不同?为什么执行时间有所不同?

由于您的方法是异步的,因此只需全部调用即可,而不是单独等待它们,而是等待所有方法以确保所有三个异步过程均已完成。然后,您可以await再次使用来解开结果:

// start all asynchronous processes at once for all three properties
var oneTask = item.propertyOne.GetAsync();
var twoTask = item.propertyTwo.GetAsync();
var threeTask = item.propertyThree.GetAsync();

// await the completion of all of those tasks
await Task.WhenAll(oneTask, twoTask, threeTask);

// access the individual results; since the tasks are already completed, this will
// unwrap the results from the tasks instantly:
var oneResult = await oneTask;
var twoResult = await twoTask;
var threeResult = await threeTask;

一般来说,异步的东西,避免调用打交道时.GetResult().Result.Wait()不惜一切代价。如果您有异步过程,那么这两种方法都无济于事。


回复您的评论:

我假设代码会进入并行的foreach中,对吗?

不,您不会Parallel.ForEach在这里使用,因为您仍在调用异步进程。Parallel.ForEach用于将工作加载到多个线程,但这不是您要在此处执行的操作。您拥有异步进程,这些进程可以同时运行而无需其他线程。

因此,如果您有很多要异步调用的东西,只需将它们全部调用并收集Tasks以便以后等待。

但是,如果请求必须是顺序的,例如分页响应,其中第一个请求将返回下一个页面请求的URL,依此类推?

然后,您将需要使调用彼此依赖,await以确保在完成异步过程之前可以继续进行调用例如,如果propertyTwo呼叫取决于propertyOne,那么您仍然可以进行所有 propertyOne呼叫,并且仅在完成呼叫后才继续。

如果将逻辑拆分为单独的方法,则会发现这变得更加容易:

var itemTasks = items.Select(item => GetPropertiesOneTwoThreeAsync(item));
await Task.WhenAll(itemTasks);

private Task GetPropertiesOneTwoThreeAsync(Item item)
{
    // get the properties sequentially
    var oneResult = await item.propertyOne.GetAsync();
    var twoResult = await item.propertyTwo.GetAsync();
    var threeResult = await item.propertyThree.GetAsync();
}

另外,如果调用方法不是异步的,Task.WhenAll(oneTask, twoTask, threeTask).GetAwaiter().GetResult()在这种情况下是否合适?

不能。从同步方法中调用异步方法通常不是您应该做的事情。如果调用异步方法,则应使调用方法也异步。有一种方法可以使这项工作正常进行,但是您将不得不处理潜在的僵局,并且通常应该知道您在做什么。另请参阅此问题

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用Guzzle 6创建异步json请求池以发送到API端点的正确方法是什么?

来自分类Dev

REST API响应的正确方法是什么?

来自分类Dev

多个异步数据发送的正确方法是什么?

来自分类Dev

在python / django中异步发送邮件的正确方法是什么?

来自分类Dev

ReactJS 异步全局 API 请求方法,如何处理响应?

来自分类Dev

将许多请求发送到Google Maps Geocoding API的正确方法是什么?

来自分类Dev

在生成 Excel 或 PDF 文件作为响应的 REST API 中处理异常的正确方法是什么?

来自分类Dev

通过使用 scapy 发送 ARP 请求并捕获响应来扫描本地网络的正确方法是什么?

来自分类Dev

授权此REST API请求的“正确方法”是什么?

来自分类Dev

异步更新UI的正确方法是什么?

来自分类Dev

呈现异步功能的正确方法是什么?

来自分类Dev

什么是处理异步请求的最佳方法

来自分类Dev

使用 dask 发送并行 API 请求和错误处理

来自分类Dev

React Hooks:在组件内部处理异步setState的正确方法是什么?(uploadProgress axios)

来自分类Dev

发送Web API响应的正确方法

来自分类Dev

在React Native组件中处理HTTP响应的正确方法是什么

来自分类Dev

我可以发送错误图和响应对象作为响应吗?正确的方法是什么?

来自分类Dev

在执行HTTP请求时处理字符串的正确方法是什么?

来自分类Dev

什么是处理POST请求的正确方法

来自分类Dev

从磁盘读取并并行处理

来自分类Dev

Go处理错误的正确方法是什么

来自分类Dev

在递归方法中使用异步/等待的正确方法是什么?

来自分类Dev

解析来自4个不同API的响应的正确OOP方法是什么?

来自分类Dev

在异步响应齐发后发送休息请求

来自分类Dev

从Angular向Node js API发出HTTP请求的正确方法是什么?

来自分类Dev

在 React 中为更新的组件执行 API 请求的正确方法是什么?

来自分类Dev

用异步操作等待字典的正确方法是什么?

来自分类Dev

在异步网络调用中使用inDatabase的正确方法是什么?

来自分类Dev

rkhunter:正确处理警告的正确方法是什么?

Related 相关文章

  1. 1

    使用Guzzle 6创建异步json请求池以发送到API端点的正确方法是什么?

  2. 2

    REST API响应的正确方法是什么?

  3. 3

    多个异步数据发送的正确方法是什么?

  4. 4

    在python / django中异步发送邮件的正确方法是什么?

  5. 5

    ReactJS 异步全局 API 请求方法,如何处理响应?

  6. 6

    将许多请求发送到Google Maps Geocoding API的正确方法是什么?

  7. 7

    在生成 Excel 或 PDF 文件作为响应的 REST API 中处理异常的正确方法是什么?

  8. 8

    通过使用 scapy 发送 ARP 请求并捕获响应来扫描本地网络的正确方法是什么?

  9. 9

    授权此REST API请求的“正确方法”是什么?

  10. 10

    异步更新UI的正确方法是什么?

  11. 11

    呈现异步功能的正确方法是什么?

  12. 12

    什么是处理异步请求的最佳方法

  13. 13

    使用 dask 发送并行 API 请求和错误处理

  14. 14

    React Hooks:在组件内部处理异步setState的正确方法是什么?(uploadProgress axios)

  15. 15

    发送Web API响应的正确方法

  16. 16

    在React Native组件中处理HTTP响应的正确方法是什么

  17. 17

    我可以发送错误图和响应对象作为响应吗?正确的方法是什么?

  18. 18

    在执行HTTP请求时处理字符串的正确方法是什么?

  19. 19

    什么是处理POST请求的正确方法

  20. 20

    从磁盘读取并并行处理

  21. 21

    Go处理错误的正确方法是什么

  22. 22

    在递归方法中使用异步/等待的正确方法是什么?

  23. 23

    解析来自4个不同API的响应的正确OOP方法是什么?

  24. 24

    在异步响应齐发后发送休息请求

  25. 25

    从Angular向Node js API发出HTTP请求的正确方法是什么?

  26. 26

    在 React 中为更新的组件执行 API 请求的正确方法是什么?

  27. 27

    用异步操作等待字典的正确方法是什么?

  28. 28

    在异步网络调用中使用inDatabase的正确方法是什么?

  29. 29

    rkhunter:正确处理警告的正确方法是什么?

热门标签

归档