You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在现有异步方法中使用Task.WhenAll并行获取附件?

如何用Task.WhenAll并行获取附件?

你现有一个已在运行的异步方法GetIssuesAsync,该方法会在foreach循环中调用另一个私有异步方法GetAttachments来获取每个Issue的附件,当前是串行执行的。

原主方法代码

public async Task<IList<IssueResponse>> GetIssuesAsync(string query, string email)
{
    var fields =
        $@"key,summary,description,status,issuetype,updated,created,attachment,assignee,reporter,
            {IssueFields.RequestType}, {IssueFields.ApproversField},
            {IssueFields.MinimumNotificationsReportersField}, {IssueFields.MinimumNotificationsUsersField},
            {IssueFields.StandardNotificationsReportersField}, {IssueFields.StandardNotificationsUsersField}, {IssueFields.StandardNotificationsAssigneeField},
            {IssueFields.FullNotificationsReportersField}, {IssueFields.FullNotificationsUsersField}, {IssueFields.FullNotificationsAssigneeField}";

    var expand = "renderedFields";

    var queryParams = new Dictionary<string, string>
    {
        { "jql", query },
        { "maxResults", "100" },
        { "validateQuery", "false" },
        { "fields", fields },
        { "expand", expand }
    };

    var request = this.ConfigureGetRequest("search", queryParams: queryParams);

    var result = await this.SendRequestAsync<IssueListResponse>(request);

    var issues = result.IssueList;

    foreach (var item in issues)
    {
        item.Fields.Attachment = await GetAttachments(item.Key, email);
    }

    return issues;
}

原GetAttachments方法代码

private async Task<List<IssueAttachment>> GetAttachments(string issueKey, string email)
{
    var attachmentRequest = this.ConfigureGetRequest(issueKey, this.settings.GetAttachmentsPathUrl).AddXClientHeader(email);;

    return await this.SendRequestAsync<List<IssueAttachment>>(
               attachmentRequest,
               new List<HttpStatusCode> { HttpStatusCode.OK });
}

修改方案:用Task.WhenAll实现并行获取

只需要修改foreach循环的部分,改为先创建所有获取附件的任务,再等待全部完成后赋值:

public async Task<IList<IssueResponse>> GetIssuesAsync(string query, string email)
{
    var fields =
        $@"key,summary,description,status,issuetype,updated,created,attachment,assignee,reporter,
            {IssueFields.RequestType}, {IssueFields.ApproversField},
            {IssueFields.MinimumNotificationsReportersField}, {IssueFields.MinimumNotificationsUsersField},
            {IssueFields.StandardNotificationsReportersField}, {IssueFields.StandardNotificationsUsersField}, {IssueFields.StandardNotificationsAssigneeField},
            {IssueFields.FullNotificationsReportersField}, {IssueFields.FullNotificationsUsersField}, {IssueFields.FullNotificationsAssigneeField}";

    var expand = "renderedFields";

    var queryParams = new Dictionary<string, string>
    {
        { "jql", query },
        { "maxResults", "100" },
        { "validateQuery", "false" },
        { "fields", fields },
        { "expand", expand }
    };

    var request = this.ConfigureGetRequest("search", queryParams: queryParams);

    var result = await this.SendRequestAsync<IssueListResponse>(request);

    var issues = result.IssueList;

    // 步骤1:为每个Issue创建获取附件的任务,暂不等待执行
    var attachmentTasks = issues.Select(async item => 
    {
        item.Fields.Attachment = await GetAttachments(item.Key, email);
        return item;
    }).ToList();

    // 步骤2:等待所有附件任务并行完成
    await Task.WhenAll(attachmentTasks);

    return issues;
}

补充说明

  • 这样修改后,所有GetAttachments请求会同时发起并行执行,相比原来的串行等待,能显著减少整体耗时。
  • 如果issues数量过大(比如远超过100),建议添加并发限制(例如用SemaphoreSlim),避免触发目标API的限流策略,导致请求失败。

内容的提问来源于stack exchange,提问作者Eugene Sukh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 01:45:55