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