I need to call the web service several times to get data, and then put those data into my database, so I\'ve got the following code:
foreach (string v in options
This would initiate asynchronous call
public delegate IList<MySampleNode> SaveToDb(IList<MySampleNode> myParam);
SaveToDb _saveToDb= new SaveToDb(objService.SaveToDb);
IAsyncResult asyncSearchResult = saveToDb.BeginInvoke(input,null,null)
This would wait for execution to complete and return value:-
IList<MySampleNode> result=asyncSearchResult EndInvoke();
To improve the scalability (i.e., the number of request your web app can serve simultaneously), you need to reduce the number of threads your app is using for each requests. So, instead of waiting for all threads to be finished, you should use naturally asynchronous APIs, which don't block a thread while the operation is pending. More details on this can be found here.
If you can use .NET 4.5, your specific case might be improved like this:
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<IList<MySampleNode>> GetDataAsync(string v)
{
IList<MySampleNode> nodes = null;
using (var client = new WsClient())
{
IEnumerable<IWsObject> wsNodes =
await client.getNodesAsync(new getClassLevel { code = v });
nodes = ProcessData(wsNodes);
}
return nodes;
}
The client-side proxy for WsClient
probably already has an async version of getNodes
, called getNodesAsync
(if not, check this). ProcessDataAsync
starts a bunch of parallel non-blocking GetDataAsync
tasks (for each node), and asynchronously awaits their completion. That's what makes this code scale well.
You might be able to further improve ProcessDataAsync
by saving the data asynchronously, i.e. await _dbService.SaveToDbAsync(nodes)
, if you can leverage the use of asynchronous Task
-based DB API (e.g, with EF6).
This downloads all in parallel and stores them into the DB with one write.
var tasks = options.Select(o => Task.Run(() => GetData(o)));
Task.WaitAll(tasks.ToArray());
var nodes = tasks.SelectMany(t => t.Result);
_dbService.SaveToDb(nodes);