亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用異步等待進行多個服務調用的最佳方式是什么

使用異步等待進行多個服務調用的最佳方式是什么

C#
哆啦的時光機 2022-08-20 17:45:35
作為異步和等待最佳實踐的一部分,建議不要使用 Task.Run。我有一個服務,它對第三方服務進行多次調用,我們使用異步來進行這些調用。我正在尋找有關以下代碼改進的建議。  public interface IRouteService{     Task<IEnumerable<Route>> GetRoute(Coordinates orign, Coordinates destination);}public class RouteProvider{    private readonly IRouteService _routeService;     public RouteProvider(IRouteService routeService)    {        _routeService = routeService;    }    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(Task.Run(async () =>                {                  var response=  await _routeService.GetRoute(origin, destination);                    foreach (var item in response)                    {                        routes.Add(item);                    }                }));            }        }        Task.WaitAll(tasks.ToArray());        return routes;    }}public class Route{    public string Distance { get; set; }    public Coordinates Origin { get; set; }    public object Destination { get; set; }    public string OriginName { get; set; }    public string DestinationName { get; set; }}public class  Coordinates{    public float Lat { get; set; }    public float Long { get; set; }}
查看完整描述

3 回答

?
慕妹3146593

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 );

}


查看完整回答
反對 回復 2022-08-20
?
忽然笑

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()


查看完整回答
反對 回復 2022-08-20
?
慕沐林林

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


但是,僅當結果需要很長時間才能處理時,才需要這樣做。否則,根本不需要單獨的線程。


查看完整回答
反對 回復 2022-08-20
  • 3 回答
  • 0 關注
  • 202 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號