具有排序结果的异步多个Web服务请求

时间:2018-07-06 07:11:44

标签: c# .net asynchronous async-await task-parallel-library

鉴于一定数量的请求对象(最多9个),我需要异步地调用Web服务端点相同的次数。对于public class TabViewPagerAdapter extends FragmentPagerAdapter { private String[] title; public TabViewPagerAdapter(FragmentManager manager, String[] titleArray) { super(manager); this.title = titleArray; } @Override public Fragment getItem(int position) { return TabFragment.getInstance(position); } @Override public int getCount() { return title.length; } @Override public CharSequence getPageTitle(int position) { return title[position]; } } ,我们使用.NET 4.0delegate实现了这一目标。

是否有更好的方法将IAsyncResultasyc/await或将两者与TPL结合使用?

按照此answer的建议,将.NET 4.6.1Parallel.ForEach一起使用将是最佳选择吗?

同步代码示例:

ConcurrentBag

编辑/更新1 :基于@Thierry的回答,我创建了一个示例代码,假设请求和响应对象中都有一个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 } 属性来标记请求/响应订购:

Order

编辑/更新2 :基于this线程,我对更新1进行了一些更改:

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
}

需求摘要:

  • 使用不同的参数异步地将多个Web服务请求发送到同一端点。
  • 将Web服务结果以与请求相同的顺序添加到列表中(好像是同步的)。

2 个答案:

答案 0 :(得分:1)

因为每个任务的完成时间都不一样,所以我认为您应该对请求进行编号,并以此编号来排序响应。

在请求中,您初始化一个数字,并将此数字传递给相关联的响应。最后,当我得到结果时,我将其排序。 像这样:

    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;
    }

答案 1 :(得分:0)

我认为您可以使用Task.WaitAll来使代码以异步方式工作,并且看起来也会更漂亮:

public List<WbsResponse> GetWbsResults()
{
    List<WbsRequest> requests = CompileWbsRequests();
    var responses = await Task.WhenAll(requests.Select(CallWebService));
    return responses;
}

但是您必须按如下所示修改此方法以返回任务:

private async Task<WbsResponse> CallWebService(WbsRequest request)
{
    //Call web service
}