2014-10-22 27 views
14

Başka bir geliştiriciden miras aldığım bir windows hizmetim var, çok yavaş çalışıyor ve eBay API'sine çok sayıda yavaş çağrı var. Çok fazla refactoring yapmadan hızlandırmak istiyorum.Async dönüş değerlerinin nasıl kullanılacağını bekliyor

Bu yavaş çağrıdan bazılarını eşzamansız çalıştırmaya çalışmak için C# async/await kullanmaya bakmaya başladım.

Ben aşağıda aramaları çok kılan bir 1 çok yoğun bir yöntem var: İşte ben başarmak için çalışıyorum ne

getProducts 
getCategories 
getVehicles 
getImages 

Düşüncelerim ben sadece async için yöntemlerini değiştirmek ve katkı sağlayabileceğini edildi

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>&nbsp;" + s + "</li>"; 
       } 
      } 
     } 
    } 
    return additionalProductDetails; 
} 

Sonra bekliyor onları çağırır:

Task<String> additionalProductDetials = ebayPartNumbers.ProcessAdditionalProductDetialsAsync(item); 
Task<PartNumberCollection> partNumberCollection = ebayPartNumbers.ProcessPartNumbersAsync(item); 


await Task.WhenAll(partNumberCollection, additionalProductDetials); 
aşağıda dönüş tipine

İade edilen türleri nasıl alabilirim, böylece bunları kullanabilirim? Sadece partNumberCollection kullanmayı denedim, ancak yalnızca await özelliklerine sahip. Görev sınıfına

+1

"ProcessAdditionalProductDetialsAsync" içinde "bekliyor". Bu senin gerçek kodun mu yoksa gerçekten "bekle" mi yapıyor? EBay API'si nereden geliyor? –

+1

Evet, derleyici bu yöntemin beklemediğini, ancak beklemenin ana yöntemde olduğunu uyarır. –

+1

Derleyici uyarısına dikkat etmelisiniz; Bu yöntemde bir “bekle” * olması gerekir * eğer bu bir “uyumsuz” ise. Arka plan iş parçacığı üzerinde kod yürütmek istiyorsanız, 'Task.Run' kullanın; eğer G/Ç yapmak isterseniz (ör., eBay API'sı), doğal olarak eşzamansız yöntemleri kullanmalıdır. –

cevap

18

Kullanım Result özelliği: Çok tamamlamış geçtiğin görevlerin tümünü demektir

Task.WhenAll tarafından döndürülen görev tamamlamış ise
await Task.WhenAll(partNumberCollection, additionalProductDetials); 

var partNumberCollectionResult = partNumberCollection.Result; 
var additionalProductDetialsResult = additionalProductDetials.Result; 
+5

Bir "AggregateException" daki istisnaları sarmamak için "Sonuç" yerine "bekle" yi kullanmalısınız. –

12

. Bu da, her bir görevin Result özelliğini, engelleme riski olmadan kullanabilmeniz anlamına gelir.

string details = additionalProductDetials.Result; 

Alternatif olarak, diğer zaman uyumsuz koduyla tutarlılık için, görevleri bekliyor olabilir:

string details = await additionalProductDetials; 

Yine, bu engellememe garanti edilir - daha sonra nedense Task.WhenAll kaldırırsanız ve (örneğin Parça numarası tahsilatına girmeden önce başka bir görevi başlatmak için ayrıntıları kullanmaktan mutluluk duyarsınız) kodu değiştirmenize gerek yoktur.

7

async yönteminiz await işleçlerinden yoksundur ve eşzamanlı olarak çalışır. engelleme API'sini çağırırken arka plan iş parçacığına cpu-bağlı çalışma yapmak için Task.Run()'u kullanabilirsiniz.

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>&nbsp;" + s + "</li>"; 
        } 
       } 
      } 
     } 
     return additionalProductDetails; 
    }); 
} 

ve

var detail = await ProcessAdditionalProductDetialsAsync(itemType); 
var result = ProcessAdditionalProductDetialsAsync(itemType).Result; 
+0

Bunu çağıran ana yöntem, async ile işaretlenir ve Task.WhenAll beklemesini kullanır, bu daha sonra yukarıdaki eşzamansız yöntemi çalıştırmaz mı? –

+0

evet, ancak yalnızca Task.WhenAll() 'işlevini kullanırsanız yapar. –

+0

Evet, sorudaki son kod satırına bakın, teşekkürler –

-1

bu kodu deneyin sonucu olsun:

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>&nbsp;" + s + "</li>"; 
       } 
      } 
      } 
     } 
     return retval; 
    } 
    return additionalProductDetails; 
} 

Kullanımı: derleyici olmadan `async` kullanma konusunda size bir uyarı vermesi gereken

private async void GetAdditionalProductDetailsAsync(Action<string> callback) { 
    string apd = await ProcessAdditionalProductDetialsAsync(); 
    callback(apd); 
} 

private void AdditionalProductDetailsRetrieved(string apd) { 
    // do anything with apd 
}