2015-12-24 47 views
1

我有下面的簡化代碼,它可以異步獲得來自多個運營商的運輸費率,並想知道是否值得轉換爲使用異步/等待方法,如果是的話,那麼最好的方法是什麼?或者如果它的工作現在好了,它真的不值得付出努力?謝謝。是否從Task <>。Factory.StartNew/Task.Factory.ContinueWhenAll()轉換爲async/await?

List<Task<ShippingRateCollection>> lstTasks = new List<Task<ShippingRateCollection>>(); 
Task<ShippingRateCollection> t; 

t = Task<ShippingRateCollection>.Factory.StartNew(() => { return GetUPSRates(...); }); 
lstTasks.Add(t); 

t = Task<ShippingRateCollection>.Factory.StartNew(() => { return GetUSPSRates(...); }); 
lstTasks.Add(t); 

t = Task<ShippingRateCollection>.Factory.StartNew(() => { return GetFedExRates(...); }); 
lstTasks.Add(t); 

//wait until all requests complete (or error out) 
Task.Factory.ContinueWhenAll(lstTasks.ToArray(), (tasks) => 
{ 
    //wrap all exceptions into 1 AggregateException 
    Task.WaitAll(tasks); 
}); 

foreach (Task<ShippingRateCollection> task in lstTasks) 
{ 
    foreach (ShippingRate rate in task.Result) 
    { 
     ... //display rate 
    } //next returned rate 
} 
+2

在你的代碼貼延續什麼都不做。你知道嗎? – usr

回答

2

你應該肯定它重構爲async/await,如果你可以讓Get*Rates方法異步。在你當前的代碼中,你可以在單獨的線程上執行它們,以阻止等待I/O完成的線程。這太浪費了。

如果你可以讓這些方法異步,代碼可能是這樣的:

var tasks = new Task<ShippingRateCollection>[] 
{ 
    GetUPSRatesAsync(), 
    GetUSPSRatesAsync(), 
    GetFedExRatesAsync() 
}; 

ShippingRateCollection[] results = await Task.WhenAll(tasks); 

// process results 

即使你有同步GetRates工作方法,代碼重構,以async/await將簡化它。

+1

但是隻有一個錯誤將被丟棄。他似乎很關心收集他們。 – usr

+0

我改變了代碼,如上所示,這絕對是更清潔;但是,如果我追蹤代碼執行,它將在同一個線程ID上依次運行每個GetRates調用。在每個GetRates調用中,都會有一個同步的Web服務調用返回速率,所以我認爲它在那個時候會阻塞,這就是爲什麼它不能同時啓動它們的原因?謝謝。 –

1

我會考慮使用Microsoft的Reactive Framework。您可以使用此代碼:

var fs = new Func<ShippingRateCollection>[] 
{ 
    () => GetUPSRates(...), 
    () => GetUSPSRates(...), 
    () => GetFedExRates(...), 
}; 

var query = 
    from f in fs.ToObservable() 
    from rate in Observable.Start(f) 
    select rate; 

query 
    .Subscribe(rate => 
    { 
     //display rate 
    }); 

代碼異步運行,併爲他們提供而不是等待他們全部完成.Subscribe(...)方法將立即返回結果。

如果你想讓他們完成,然後你可以改變這樣的代碼:

query 
    .ToArray() 
    .Subscribe(rates => 
    { 
     foreach (ShippingRate rate in rates) 
     { 
      //display rate 
     } 
    }); 

剛的NuGet「RX-主」,以獲得所需的位。

0

Jakub Lortz的回答的不太詳細的版本:

var results = await Task.WhenAll(
    GetUPSRatesAsync(), 
    GetUSPSRatesAsync(), 
    GetFedExRatesAsync()); 
相關問題