如何在现有异步方法中使用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
相关产品推荐
相关产品推荐

