我需要多次调用 Web 服务来获取数据,然后将这些数据放入数据库中,因此我得到了以下代码:
foreach (string v in options)
{
IList<MySampleNode> nodes = _pi.GetData(v);
_dbService.SaveToDb(nodes);
}
GetData 实现如下所示:
public IList<MySampleNode> GetData(string v)
{
IList<MySampleNode> nodes = null;
try
{
var client = new WsClient();
IEnumerable<IWsObject> wsNodes = client.getNodes(new getClassLevel { code = v });
nodes = ProcessData(wsNodes);
}
return nodes;
}
我想将此代码修改为异步版本,以便在单独的线程中运行每个下载/保存到数据库并等待所有线程完成,或者也许还有其他一些方法来提高此类代码的性能,您能帮忙吗我?
为了提高可扩展性(即您的 Web 应用程序可以同时处理的请求数量),您需要减少应用程序用于每个请求的线程数量。所以,而不是等待所有线程完成,您应该使用自然异步 API,它不会在操作挂起时阻塞线程。有关此的更多详细信息,请参阅here.
如果您可以使用.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<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;
}
客户端代理WsClient
可能已经有一个异步版本getNodes
,称为getNodesAsync
(如果没有,请检查this). ProcessDataAsync
启动一堆并行非阻塞GetDataAsync
任务(对于每个节点),并异步等待它们完成。这就是使该代码具有良好扩展性的原因。
你或许可以进一步提高ProcessDataAsync
通过异步保存数据,即await _dbService.SaveToDbAsync(nodes)
,如果你可以利用异步Task
基于 DB API(例如,使用EF6).
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)