异步调用webservice并等待所有线程完成

我需要多次调用Web服务来获取数据,然后将这些数据放入我的数据库中,所以我有以下代码:

foreach (string v in options) { IList nodes = _pi.GetData(v); _dbService.SaveToDb(nodes); } 

GetData实现如下所示:

 public IList GetData(string v) { IList nodes = null; try { var client = new WsClient(); IEnumerable wsNodes = client.getNodes(new getClassLevel { code = v }); nodes = ProcessData(wsNodes); } return nodes; } 

我想将此代码修改为异步版本,以便在单独的线程中运行每次下载/保存到数据库并等待所有线程完成,或者可能还有其他一些方法来提高此类代码的性能,请你帮忙吗我?

要提高可伸缩性(即,您的Web应用程序可以同时提供的请求数),您需要减少应用程序为每个请求使用的线程数。 因此,您应该使用自然异步的API,而不是等待所有线程完成 ,这些API在操作挂起时不会阻塞线程。 有关这方面的更多细节可以在这里找到。

如果您可以使用.NET 4.5,您的具体情况可能会像这样改进:

 public void Page_Load(object sender, EventArgs e) { RegisterAsyncTask(new PageAsyncTask(ProcessDataAsync)); } public async Task ProcessDataAsync() { var tasks = options.Select(v => _pi.GetDataAsync(v)); await Task.WhenAll(tasks); var nodes = tasks.Select(t => t.Result); _dbService.SaveToDb(nodes); } public async Task> GetDataAsync(string v) { IList nodes = null; using (var client = new WsClient()) { IEnumerable wsNodes = await client.getNodesAsync(new getClassLevel { code = v }); nodes = ProcessData(wsNodes); } return nodes; } 

WsClient的客户端代理可能已经有一个异步版本的getNodes ,名为getNodesAsync (如果没有,请检查一下 )。 ProcessDataAsync启动一堆并行的非阻塞GetDataAsync任务(对于每个节点),并异步等待它们完成。 这就是使这个代码很好地扩展的原因。

您可以通过异步保存数据来进一步改进ProcessDataAsync ,即await _dbService.SaveToDbAsync(nodes) ,如果您可以利用异步的基于Task的DB API(例如,使用EF6 )。

这将全部并行下载并通过一次写入将它们存储到DB中。

 var tasks = options.Select(o => Task.Run(() => GetData(o))); Task.WaitAll(tasks.ToArray()); var nodes = tasks.SelectMany(t => t.Result); _dbService.SaveToDb(nodes); 

这将启动异步调用

  public delegate IList SaveToDb(IList myParam); SaveToDb _saveToDb= new SaveToDb(objService.SaveToDb); IAsyncResult asyncSearchResult = saveToDb.BeginInvoke(input,null,null) 

这将等待执行完成并返回值: –

 IList result=asyncSearchResult EndInvoke();