具有有序结果的异步多个 Web 服务请求
Asynchronous multiple Web Service requests with ordered result
给定一定数量的请求对象(最多 9 个),我需要异步调用相同次数的 Web 服务端点。对于 .NET 4.0
,我们使用 delegate
和 IAsyncResult
来实现这一点。
使用 asyc/await
、TPL
或两者结合 .NET 4.6.1
是否有更好的方法?
将 Parallel.ForEach
与 ConcurrentBag
结合使用是否会如本 answer 中所建议的那样最佳?
同步代码示例:
public List<WbsResponse> GetWbsResults()
{
List<WbsRequest> requests = CompileWbsRequests();
List<WbsResponse> results = new List<WbsResponse>();
foreach (var request in requests)
{
//Call same web service endpoint n number of times
var response = CallWebService(request);
results.Add(response);
}
//do something with results
return results;
}
private WbsResponse CallWebService(WbsRequest request)
{
//Call web service
}
Edit/Update 1:根据@Thierry 的回答,我创建了一个示例代码,假设两者都有 Order
属性标记 request/response 排序的请求和响应对象:
public List<WbsResponse> GetWbsResults()
{
List<WbsRequest> requests = CompileWbsRequests();
List<WbsResponse> results = new List<WbsResponse>();
Parallel.ForEach(requests, (request) => {
var response = CallWebService(request);
response.Order = request.Order;
results.Add(response);
});
results = results.OrderBy(r => r.Order).ToList();
//do something with results
return results;
}
private WbsResponse CallWebService(WbsRequest request)
{
//Call web service
}
Edit/Update 2:基于 this 线程,我对更新 1 做了一些更改:
await Task.Run(() => {
Parallel.ForEach(requests, (request) => {
var response = CallWebService(request);
response.Order = request.Order;
results.Add(response);
});
});
要求摘要:
- 使用不同的参数向同一终结点异步发出多个 Web 服务请求。
- 将 Web 服务结果添加到列表中的顺序与发出请求的顺序相同(就好像它是同步的)。
我认为您可以使用 Task.WaitAll
使代码以异步方式工作,它看起来也会更漂亮:
public List<WbsResponse> GetWbsResults()
{
List<WbsRequest> requests = CompileWbsRequests();
var responses = await Task.WhenAll(requests.Select(CallWebService));
return responses;
}
但是您必须如下修改此方法以return一个任务:
private async Task<WbsResponse> CallWebService(WbsRequest request)
{
//Call web service
}
因为每个任务在不同时刻完成,我认为你应该对请求进行编号,并按此编号对响应进行排序。
在请求中,您初始化一个数字并将此数字传递给关联的响应。最后,当我得到结果时,我就下单了。
像这样:
public async Task<List<WbsResponse>> GetWbsResults()
{
List<WbsRequest> requests = CompileWbsRequests();
List<Task<WbsResponse>> tasks = new List<Task<WbsResponse>>();
for (var i = 0; i < requests.Count; i++)
{
var task = new Task<WbsResponse>(() => { CallWebService(WbsRequest); });
tasks.Add(task);
}
var responses = await Task.WhenAll(tasks);
var responsesOrdered = responses.OrderBy(r => r.Order)
//do something with results
return results;
}
public List<WbsRequest> CompileWbsRequests()
{
//create requests
foreach(var request in requests)
{
request.Order += 1;
}
}
private WbsResponse CallWebService(WbsRequest request)
{
//Call web service
reponse.order = request.order;
return reponse;
}
给定一定数量的请求对象(最多 9 个),我需要异步调用相同次数的 Web 服务端点。对于 .NET 4.0
,我们使用 delegate
和 IAsyncResult
来实现这一点。
使用 asyc/await
、TPL
或两者结合 .NET 4.6.1
是否有更好的方法?
将 Parallel.ForEach
与 ConcurrentBag
结合使用是否会如本 answer 中所建议的那样最佳?
同步代码示例:
public List<WbsResponse> GetWbsResults()
{
List<WbsRequest> requests = CompileWbsRequests();
List<WbsResponse> results = new List<WbsResponse>();
foreach (var request in requests)
{
//Call same web service endpoint n number of times
var response = CallWebService(request);
results.Add(response);
}
//do something with results
return results;
}
private WbsResponse CallWebService(WbsRequest request)
{
//Call web service
}
Edit/Update 1:根据@Thierry 的回答,我创建了一个示例代码,假设两者都有 Order
属性标记 request/response 排序的请求和响应对象:
public List<WbsResponse> GetWbsResults()
{
List<WbsRequest> requests = CompileWbsRequests();
List<WbsResponse> results = new List<WbsResponse>();
Parallel.ForEach(requests, (request) => {
var response = CallWebService(request);
response.Order = request.Order;
results.Add(response);
});
results = results.OrderBy(r => r.Order).ToList();
//do something with results
return results;
}
private WbsResponse CallWebService(WbsRequest request)
{
//Call web service
}
Edit/Update 2:基于 this 线程,我对更新 1 做了一些更改:
await Task.Run(() => {
Parallel.ForEach(requests, (request) => {
var response = CallWebService(request);
response.Order = request.Order;
results.Add(response);
});
});
要求摘要:
- 使用不同的参数向同一终结点异步发出多个 Web 服务请求。
- 将 Web 服务结果添加到列表中的顺序与发出请求的顺序相同(就好像它是同步的)。
我认为您可以使用 Task.WaitAll
使代码以异步方式工作,它看起来也会更漂亮:
public List<WbsResponse> GetWbsResults()
{
List<WbsRequest> requests = CompileWbsRequests();
var responses = await Task.WhenAll(requests.Select(CallWebService));
return responses;
}
但是您必须如下修改此方法以return一个任务:
private async Task<WbsResponse> CallWebService(WbsRequest request)
{
//Call web service
}
因为每个任务在不同时刻完成,我认为你应该对请求进行编号,并按此编号对响应进行排序。
在请求中,您初始化一个数字并将此数字传递给关联的响应。最后,当我得到结果时,我就下单了。 像这样:
public async Task<List<WbsResponse>> GetWbsResults()
{
List<WbsRequest> requests = CompileWbsRequests();
List<Task<WbsResponse>> tasks = new List<Task<WbsResponse>>();
for (var i = 0; i < requests.Count; i++)
{
var task = new Task<WbsResponse>(() => { CallWebService(WbsRequest); });
tasks.Add(task);
}
var responses = await Task.WhenAll(tasks);
var responsesOrdered = responses.OrderBy(r => r.Order)
//do something with results
return results;
}
public List<WbsRequest> CompileWbsRequests()
{
//create requests
foreach(var request in requests)
{
request.Order += 1;
}
}
private WbsResponse CallWebService(WbsRequest request)
{
//Call web service
reponse.order = request.order;
return reponse;
}