c# - 优化并行HttpClient请求

时间:2018-03-30 15:50:28

标签: c# asynchronous optimization httprequest httpclient

我需要通过字符串数组并为数组的每个元素模拟HttpRequests并处理响应,但与请求时间相比,这需要的时间可以忽略不计。这就是我意识到的:

请求方法(包含在具有共享HttpClient实例的类中):

private async Task<System.Net.Http.HttpResponseMessage> GetResponseMessage(string link)
    {
        var request = new HttpRequestMessage()
        {
            RequestUri = new Uri("https://api.warframe.market/v1/items/" + link + "/orders"),
            Method = HttpMethod.Get,
        };
        client.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36");
        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
        request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
        request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("br"));
        request.Headers.Referrer = new Uri("https://warframe.market/items/" + link);
        return await client.SendAsync(request);
    }

发送请求,解压缩并分析它的方法:

    public async Task<int> GetLowestPriceForItem(string itemName)
    {
        try
        {
            var responseMessage = await GetResponseMessage(itemName);
            if (responseMessage.IsSuccessStatusCode)
            {
                byte[] byteResponse = await responseMessage.Content.ReadAsByteArrayAsync();
                byte[] decompress = BrotliDecompress(byteResponse);  //negligble time       
                string text = System.Text.Encoding.ASCII.GetString(decompress);
                WarframeMarketDeserializer deserializer = new WarframeMarketDeserializer(text);
                return deserializer.GetLowestSellPrice(); //negligble
            }
            return 0;
        }
        catch (Exception e)
        {
            throw new Exception("The price for the item wasn't properly fetched. Error message: " + e.Message);
        }
    }

为数组中的所有元素调用请求的方法:

    public async void HandleHotkey()
    {//Handles the hotkey (and does necessary checks)

        if (ForegroundWindow.IsInFocus(targetProcess.MainWindowHandle) && !KeyPressed)  //should be IsFullscreen, this is for testing
        {
            KeyPressed = true;

            string[] items = { "tigris_prime_stock", "tigris_prime_receiver", "tigris_prime_barrel", "tigris_prime_blueprint" };
            int[] itemPrices = new int[items.Length];
            WarframeMarketClient client = new WarframeMarketClient();
            var tasks = items.Select(async item =>
            {
                itemPrices[Array.IndexOf(items, item)] = await client.GetLowestPriceForItem(item);
            });
            await Task.WhenAll(tasks);
            string result = "";
            for (int i = 0; i < items.Length; i++)
            {
                result = result + items[i] + " " + itemPrices[i].ToString() + "\n ";
            }
            MessageBox.Show(result);
            KeyPressed = false;
        }
    }

发送请求的方法花费的时间最多,每个实例大约600ms(当我通过浏览器分析请求时,完全相同的Web请求需要大约200-300ms来“获取”),当我并行运行它们时,所有4请求在1.9s内发送和处理

我环顾了StackOverflow并找到了this answer并试图从中实现一些想法。即通过 ContinueWith 链接异步方法。现在发送请求的方法如下所示:

    public async Task<int> GetLowestPriceForItem(string itemName)
    {
        try
        {
            Task<HttpResponseMessage> getMessageTask = GetResponseMessage(itemName);
            Task<int> getPrice = await getMessageTask.ContinueWith(i => HandleResponseMessage(i.Result));
            return await getPrice;
        }
        catch (Exception e)
        {
            throw new Exception("The price for the item wasn't properly fetched. Error message: " + e.Message);
        }
    }

    private async Task<int> HandleResponseMessage(HttpResponseMessage message)
    {
        int itemPrice = 0;
        if (message.IsSuccessStatusCode)
        {
            Task<byte[]> byteDecompressed = message.Content.ReadAsByteArrayAsync().ContinueWith(i => BrotliDecompress(i.Result));
            Task<string> stringDecompressed = byteDecompressed.ContinueWith(i => 
            {
                return System.Text.Encoding.ASCII.GetString(i.Result);
            });
            Task itemPriceResult = stringDecompressed.ContinueWith(i =>
            {
                WarframeMarketDeserializer deserializer = new WarframeMarketDeserializer(stringDecompressed.Result);
                itemPrice = deserializer.GetLowestSellPrice();
            });
            await itemPriceResult;
            return itemPrice;             
        }
        else
        {
            throw new Exception("Response from the site (warframe.market) was invalid.");
        }           
    }

但是,所花的时间仍然是一样的。 4项大约1.9s。是否有可能加快速度以及如何加速?

感谢您阅读

0 个答案:

没有答案