异步调用Web服务并等待完成的所有线程 [英] Call webservice asynchronously and wait for all threads to be finished

查看:199
本文介绍了异步调用Web服务并等待完成的所有线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要调用Web服务多次获得数据,然后把这些数据输入到我的数据库,所以我有以下code:

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)
{
    IList<MySampleNode> nodes = _pi.GetData(v);
    _dbService.SaveToDb(nodes);
}

在实施的GetData如下所示:

the GetData implementation looks as follows:

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

我想修改此code到异步版本运行每个下载/保存到数据库中的单独的线程,并等待完成的所有线程,或者有一些其他的方法来改善这种性能code,你能帮帮我吗?

I'd like to modify this code to asynchronous version to run each download/save to database in separate thread and wait for all threads to be finished, or maybe there are some other approaches to improve the performance of such code, can you please help me?

推荐答案

要提高可扩展性(即请求数你的web应用程序可以同时服务),你需要减少你的应用程序使用的每个线程的数量要求。因此,代替的等待所有线程完成的,你应该使用自然异步的API,而操作挂起,不阻塞线程。这个更多细节可以在这里找到

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.

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

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

WsClient 可能已经有 getNodes 的异步版本,叫做<$ C $客户端代理C> getNodesAsync (如果没有,请这个)。 ProcessDataAsync 启动一束平行非阻隔 GetDataAsync 任务(每个节点)以及异步等待其完成。这是什么使这个code很好地扩展。

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.

您也许能够进一步完善 ProcessDataAsync 通过异步保存数据,即等待_dbService.SaveToDbAsync(节点),如果你可以利用采用异步的工作为主的DB API(例如,用的 EF6 )。

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).

这篇关于异步调用Web服务并等待完成的所有线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆