Async等待如何使用返回值
我有一个我从另一个开发人员inheritance的Windows服务,它运行速度非常慢,并且对eBay API有很多慢速调用。 我希望在没有太多重构的情况下加快速度。
我刚刚开始考虑使用c#async / await尝试使用这些慢速调用来运行异步。 这是我想要实现的目标:
我有一个非常繁忙的方法,可以进行如下调整:
getProducts getCategories getVehicles getImages
我的想法是我可以简单地将方法更改为async
并将Task
添加到返回类型,如下所示:
public async Task ProcessAdditionalProductDetialsAsync(ItemType oItem) { String additionalProductDetails = string.Empty; if (oItem.ItemSpecifics.Count > 0) { foreach (NameValueListType nvl in oItem.ItemSpecifics) { if (nvl.Value.Count > 0) { foreach (string s in nvl.Value) { additionalProductDetails += "" + nvl.Name + ": " + s + " "; } } } } return additionalProductDetails; }
然后等待调用它们:
Task additionalProductDetials = ebayPartNumbers.ProcessAdditionalProductDetialsAsync(item); Task partNumberCollection = ebayPartNumbers.ProcessPartNumbersAsync(item); await Task.WhenAll(partNumberCollection, additionalProductDetials);
如何获取返回的类型以便我可以使用它们? 我尝试过只使用partNumberCollection
但它只有await
属性可用。
在Task类上使用Result属性:
await Task.WhenAll(partNumberCollection, additionalProductDetials); var partNumberCollectionResult = partNumberCollection.Result; var additionalProductDetialsResult = additionalProductDetials.Result;
如果Task.WhenAll
返回的任务已完成,则表示您传递给它的所有任务也已完成。 这反过来意味着您可以使用每个任务的Result
属性,而不会有阻塞的风险。
string details = additionalProductDetials.Result;
或者,您可以等待任务,以便与其他异步代码保持一致:
string details = await additionalProductDetials;
再次,这保证不会阻止 – 如果你以后删除Task.WhenAll
由于某种原因(例如,你很高兴在获得部件号收集之前使用细节启动另一个任务)然后你不要我需要改变代码。
您的async
方法缺少await
运算符并将同步运行。 当您调用非阻塞API时,可以使用Task.Run()
在后台线程上执行cpu绑定工作。
public async Task ProcessAdditionalProductDetialsAsync(ItemType oItem) { return await Task.Run(() => { String additionalProductDetails = string.Empty; if (oItem.ItemSpecifics.Count > 0) { foreach (NameValueListType nvl in oItem.ItemSpecifics) { if (nvl.Value.Count > 0) { foreach (string s in nvl.Value) { additionalProductDetails += "" + nvl.Name + ": " + s + " "; } } } } return additionalProductDetails; }); }
并得到结果
var detail = await ProcessAdditionalProductDetialsAsync(itemType); var result = ProcessAdditionalProductDetialsAsync(itemType).Result;
试试这段代码:
public async Task ProcessAdditionalProductDetialsAsync(ItemType oItem) { String additionalProductDetails = await Task.Run(() => { if (oItem.ItemSpecifics.Count > 0) { foreach (NameValueListType nvl in oItem.ItemSpecifics) { if (nvl.Value.Count > 0) { string retval = String.Empty; foreach (string s in nvl.Value) { retval += "" + nvl.Name + ": " + s + " "; } } } } return retval; } return additionalProductDetails; }
用法:
private async void GetAdditionalProductDetailsAsync(Action callback) { string apd = await ProcessAdditionalProductDetialsAsync(); callback(apd); } private void AdditionalProductDetailsRetrieved(string apd) { // do anything with apd }