我有以下简化代码,可以异步获取多个运营商的运费,并且想知道是否值得转换为使用异步/等待方法,如果是这样,那么最好的方法是做什么呢?或者,如果现在工作正常,那真的不值得努力吗?谢谢。
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
}
答案 0 :(得分: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 :(得分:1)
我会考虑使用Microsoft的Reactive Framework。您可以使用以下代码:
public $incrementing = false;
代码以异步方式运行,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(...)
Just NuGet&#34; Rx-Main&#34;得到所需的位。
答案 2 :(得分:0)
Jakub Lortz答案的详细版本:
var results = await Task.WhenAll(
GetUPSRatesAsync(),
GetUSPSRatesAsync(),
GetFedExRatesAsync());