我有一个名为VehicleInfoFetcher
的抽象类,它通过此方法从WebClient
异步返回信息:
public override async Task<DTOrealtimeinfo> getVehicleInfo(string stopID);
我想结合这个类的两个独立实例的结果,在组合结果之前并行运行每个实例。这是在第三类CombinedVehicleInfoFetcher
(也是VehicleInfoFetcher
的子类)中完成的
这是我的代码 - 但我不太相信它并行运行任务;我做得对吗?可以优化吗?
public class CombinedVehicleInfoFetcher : VehicleInfoFetcher
{
public HashSet<VehicleInfoFetcher> VehicleInfoFetchers { get; set; }
public override async Task<DTOrealtimeinfo> getVehicleInfo(string stopID)
{
// Create a list of parallel tasks to run
var resultTasks = new List<Task<DTOrealtimeinfo>>();
foreach (VehicleInfoFetcher fetcher in VehicleInfoFetchers)
resultTasks.Add(fetcher.getVehicleInfo(stopID, stopID2, timePointLocal));
// run each task
foreach (var task in resultTasks)
await task;
// Wait for all the results to come in
await Task.WhenAll(resultTasks.ToArray());
// combine the results
var allRealtimeResults = new List<DTOrealtimeinfo>( resultTasks.Select(t => t.Result) );
return combineTaskResults(allRealtimeResults);
}
DTOrealtimeinfo combineTaskResults(List<DTOrealtimeinfo> realtimeResults)
{
// ...
return rtInfoOutput;
}
}
修改
一些非常有用的答案,这是一个重写的例子,以帮助下面与我们讨论:
public override async Task<object> combineResults()
{
// Create a list of parallel tasks to run
var resultTasks= new List<object>();
foreach (AnotherClass cls in this.OtherClasses)
resultTasks.Add(cls.getResults() );
// Point A - have the cls.getResults() methods been called yet?
// Wait for all the results to come in
await Task.WhenAll(resultTasks.ToArray());
// combine the results
return new List<object>( resultTasks.Select(t => t.Result) );
}
}
答案 0 :(得分:2)
几乎所有任务都已经开始了。可能,任何fetcher.getVehicleInfo
返回已经开始。所以你可以删除:
// run each task
foreach (var task in resultTasks)
await task;
Task.WhenAll
更快,并且具有更好的错误行为(您希望传播所有异常,而不仅仅是您偶然遇到的第一个异常)。
此外,await不会启动任务。它等待完成。你必须安排单独启动任务,但正如我所说的,几乎所有任务都已经启动了。这也是最好的做法。
<小时/> 为了帮助我们在评论中进行讨论:
Task Test1() { return new Task(() => {}); }
Task Test2() { return Task.Factory.StartNew(() => {}); }
Task Test3() { return new FileStream("").ReadAsync(...); }
Task Test4() { return new TaskCompletionSource<object>().Task; }