首页 > 解决方案 > 存储在字典对象中的异步 Http GET 任务

问题描述

我正在努力减少延迟并提高我的应用程序的响应能力。在我的 API 控制器(Asp .NET Core)中

我正在使用 anHttpClient对服务器执行多个请求,获取事件和任务信息。

我为用户关联的每个组执行两个请求(我使用 Microsoft Graph API 获取此信息);一种用于事件,一种用于任务。

然后我等待他们的结果,如果他们不返回 null,则将它们附加到我的字典对象中,以组的名称命名。

返回对象:

Group 1 
    -- Incidents ArrayList
    -- Tasks ArrayList

Group 2 
    -- Incidents ArrayList
    -- Tasks ArrayList
...

我的代码如下:

Dictionary<string, ArrayList> final;
Microsoft.Graph.Group group_details;
string group_name;

using (var client = ClientFactory.GetClientAsync(_apiCredentials))
{
    //for each group send request to get past 30 day's incidents and tasks
    foreach (var group in groups.CurrentPage)
    {
        //request to Graph API to get name of group for query
        try
        {
            group_details = await _graphServiceClient.Groups[group.Id].Request()
                .GetAsync();
            group_name = group_details.DisplayName.Replace("#", "").Trim();

            //creates async tasks for fetching Incidents and Tasks
            var getIncidentsTask = GetIncidents(client, startDate, group_name);
            var getTasksTask = GetTasks(client, startDate, group_name);

            //awaits values
            var Incidents = await getIncidentsTask;
            var Tasks = await getTasksTask;

            //if both Incidents and Tasks exist for current group
            if (Incidents != null && Tasks != null)
            {
                final.Add(group_name, new ArrayList());
                final[group_name].Add(Incidents);
                final[group_name].Add(Tasks);
            }
        }
        catch(Exception e)
        {
            _logger.LogError(e.Message);
        }
    }
}

我知道有一种更高级的方法可以等待这些任务。我试图使用Task.WhenAll(),但是这只适用于 ,IEnumerable所以我必须在每个组中挖掘一个层并循环遍历每个组,同时使用此语句在完成每组事件/任务时生成一个任务。

我的目标是让所有任务在后台运行完成,同时尽可能少地阻塞线程,然后如果每组结果不为空,则将它们附加到我的返回对象中。

如果有人对此有任何建议,我将不胜感激。

标签: c#asynchronousasp.net-core-mvc

解决方案


这是“一个”解决方案。它允许您并行等待所有任务,同时保持每个组捆绑的结果。理论上,如果您愿意,如果您选择使用并发集合,则可以将向字典/数组列表添加值的逻辑移动到选择本身。

对不起,如果我在这里搞砸了。我尽量不要过度假设任何事情。Intellisense 也不起作用,因为您没有包含几个变量。

using (var client = ClientFactory.GetClientAsync(_apiCredentials))
{
    var results = await Task.WhenAll(
        groups.CurrentPage
            .Select(async group => {
                try
                {
                    var details = await _graphServiceClient.Groups[group.Id].Request().GetAsync();
                    var name = details.DisplayName.Replace("#", "").Trim();
                    // fetching Incidents and Tasks
                    var incidentsTask = GetIncidents(client, startDate, name);
                    var tasksTask = GetTasks(client, startDate, name);
                    await Task.WhenAll(incidentsTask, tasksTask);
                    return new { name, incidents = incidentsTask.Result, tasks = tasksTask.Result };
                }
                catch (Exception e)
                {
                    _logger.LogError(e.Message);
                    return null;
                }
            }));
    foreach (var result in results.Where(x => x != null))
    {
        //if both Incidents and Tasks exist for current group
        if (result.incidents != null && result.tasks != null)
        {
            final.Add(result.name, new ArrayList { 
                result.incidents,
                result.tasks
            });
        }
    }
}

推荐阅读