3 回答

TA贡献1820条经验 获得超9个赞
对于这样的问题,使用 LINQ 很方便。LINQ 生成不可变的结果,因此您可以避免并发问题,也不需要任何专用集合。
一般来说,使用LINQ或类似的编程技术(即像函数式程序员一样思考)将使多线程更容易。
public async Task<IEnumerable<Route>> GetRoutes(IEnumerable<Coordinates> origins, IEnumerable<Coordinates> destinations)
{
var tasks = origins
.SelectMany
(
o => destinations.Select
(
d => _routeService.GetRoute(o, d)
)
);
await Task.WhenAll( tasks.ToArray() );
return tasks.SelectMany( task => task.Result );
}

TA贡献1806条经验 获得超5个赞
正如评论中指出的那样,我建议您可以使用 来确定要完成的所有任务并获得结果。为此,您可以更新代码,如下所示。Task.WhenAll()return await Task.WhenAll(tasks);
public async Task<IEnumerable<Route>> GetRoutes(IEnumerable<Coordinates> origns, IEnumerable<Coordinates> destinations)
{
ConcurrentBag<Route> routes = new ConcurrentBag<Route>();
List<Task> tasks = new List<Task>();
foreach (var origin in origns)
{
foreach (var destination in destinations)
{
tasks.Add(_routeService.GetRoute(origin, destination));
}
}
var response = await Task.WhenAll(tasks);
foreach (var item in response)
{
routes.Add(item);
}
return routes;
}
}
由于所有调用都将返回相同的类型,因此无需在其他循环中启动第二个调用。此外,通过这种方式,您将避免锁定线程执行,并且您的程序将运行得更加同步。要查看 与 之间的区别,您可以查看此内容。foreachTask.WaitAll()WhenAll()WaitAll()

TA贡献2016条经验 获得超9个赞
您可以使用延续,而不是使用该方法直接创建任务。Task.Run
foreach (var origin in origns)
{
foreach (var destination in destinations)
{
tasks.Add(
_routeService.GetRoute(origin, destination)
.ContinueWith(response =>
{
foreach (var item in response.Result)
routes.Add(item);
})
);
}
}
因此,该方法将异步执行,而无需创建单独的线程。从中获得的结果将在单独的线程(任务)中处理。GetRoute
但是,仅当结果需要很长时间才能处理时,才需要这样做。否则,根本不需要单独的线程。
- 3 回答
- 0 关注
- 170 浏览
添加回答
举报