Mario Stoilov
Mario Stoilov

Reputation: 3447

WebApi and async methods

I am fairly lost in the new async methods in .NET. My problem is I have a method

private static List<RouteDTO> ParseRoutesHTML(string result, Cookie cookie)
        {
            List<RouteDTO> routes = new List<RouteDTO>();
            HtmlDocument htmlDocument = new HtmlAgilityPack.HtmlDocument();
            htmlDocument.LoadHtml(result);
            int contNumber = 1;
            while (true)
            {

                HtmlNode divNode = htmlDocument.GetElementbyId("cont"+contNumber);
                if (divNode != null)
                {
                    HtmlNode table = divNode.SelectSingleNode("table");
                    if (table != null)
                    {
                        string fullRoute = "";
                        HtmlNodeCollection dataRows = table.SelectNodes("tr[@align]");
                        RouteDTO currentRoutes = new RouteDTO();
                        foreach (var dataRow in dataRows)
                        {
                            currentRoutes.routes.Add(ParseRouteDataRow(dataRow));
                            //fullRoute+=ParseDataRow(dataRow)+" then ";
                        }
                        HtmlNodeCollection lastRow = table.SelectNodes("tr").Last().SelectSingleNode("td/div").SelectNodes("a");
                        HtmlNode mapLink = lastRow[1];

                        ParseMap(currentRoutes, mapLink);


                        HtmlNode priceLink = lastRow[2];
                        string priceHref = priceLink.Attributes["href"].Value;

                        ParcePrice(currentRoutes, priceHref, cookie);

                        routes.Add(currentRoutes);
                    }
                    contNumber++;
                }
                else
                {
                    break;
                }
            }
            return routes;
        }

private static void ParcePrice(RouteDTO currentRoutes, string priceHref, Cookie cookie)
        {
            var cookieContainer = new CookieContainer();
            var handler = new HttpClientHandler() { CookieContainer = cookieContainer };
            var httpClient = new HttpClient(handler);
            cookieContainer.Add(cookie);

            var priceMessage = httpClient.GetByteArrayAsync("http://razpisanie.bdz.bg" + priceHref).Result;
            var priceResponse = Encoding.UTF8.GetString(priceMessage, 0, priceMessage.Length - 1);
            var priceInfo = ParsePriceResponse(priceResponse);
            currentRoutes.priceInfo = priceInfo;
        }

        private static void ParseMap(RouteDTO currentRoutes, HtmlNode mapLink)
        {
            var httpClient = new HttpClient();
            string mapHref = mapLink.Attributes["href"].Value;
            var mapMessage = httpClient.GetByteArrayAsync("http://razpisanie.bdz.bg" + mapHref).Result;
            var mapResponse = Encoding.UTF8.GetString(mapMessage, 0, mapMessage.Length - 1);
            string mapString = ParseMapResponse(mapResponse);
            currentRoutes.imageBase64 = mapString;
        }

Please never mind the crappy HTML parsing (the site itself is awful), but take a look at the ParseMap and ParsePrice methods. These make web requests and therefore need to be asynchronous. The problem is if I make them async I am afraid that they will not be finished when the return routes is called (that is actually what happened when I made the void async, but I found out that is a BIG no-no). How can I make the return routes wait for all the async methods to finish before it is called?

Upvotes: 1

Views: 557

Answers (1)

Darrel Miller
Darrel Miller

Reputation: 142044

Return the Task from each of your parse methods, put them in a list or array and then do use Task.WhenAll to create a task that will complete when all the tasks are done and return that from your action.

Upvotes: 1

Related Questions