簡體   English   中英

異步調用Webservice並等待所有線程完成

[英]Call webservice asynchronously and wait for all threads to be finished

我需要多次調用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,這些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<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 (如果沒有,檢查這個 )。 ProcessDataAsync (針對每個節點)啟動一堆並行的非阻塞GetDataAsync任務,並異步等待其完成。 這就是使此代碼可擴展的原因。

你也許能夠進一步提高ProcessDataAsync通過異步地保存數據,即await _dbService.SaveToDbAsync(nodes) ,如果你可以利用使用異步的Task為基礎的DB API(例如, EF6 )。

這將並行下載所有文件,並將它們一次寫入就存儲到數據庫中。

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<MySampleNode> SaveToDb(IList<MySampleNode> myParam);
 SaveToDb _saveToDb= new SaveToDb(objService.SaveToDb);
 IAsyncResult asyncSearchResult = saveToDb.BeginInvoke(input,null,null)

這將等待執行完成並返回值:

IList<MySampleNode> result=asyncSearchResult EndInvoke();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM