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 }