C#HttpClient;如何进行安全的异步调用?

时间:2017-01-11 17:07:50

标签: c# multithreading asynchronous httpclient

我有一个运行第三方API的网站。此API将告诉我用户帐户的值。 API已经没有响应,这凸显了我的代码中的一个缺陷。我得到例外"线程被中止。"在调用周围的try-catch陷阱中,在EventViewer中我可以看到HttpException RequestTimedOut。

我正在尝试以同步方式使用HttpClient。这在API响应时工作正常,但现在它已经分崩离析,因为API响应非常慢。

我有一个概述页面,试图收集所有用户的所有帐户值。 有3种类型的用户(CLIENT,LIAISON,MEMBER)。该页面为每种类型的帐户进行三次异步Javascript调用。有三个电话的事实(很可能)是一个红鲱鱼,但我宣称它是安全的。

服务器接听每个电话,获取每个电话的用户。因此,对于CLIENT调用,系统会提取所有CLIENT用户,并按顺序逐步执行。它为每个CLIENT用户发出一个HTTP请求来获取帐户值。

每个调用都有一个为它创建的新HttpClient对象,包含在using语句中。

我强烈怀疑IIS正在发现空闲线程并将其关闭,这是公平的。

如何进行API调用以便将线程返回池中,直到我收到响应?

    private static string getTotalAssets(string blockChainAddress, string identity)
    {
        var prefix = "getTotalAssets() - ";
        string msg = "";

        using (var handler = new HttpClientHandler { UseCookies = false, PreAuthenticate = true })
        using (var client = new HttpClient(handler))
        {
            // Timeout
            TimeSpan tsTimeout = new TimeSpan(0, 0, 0, _timeout);
            client.Timeout = tsTimeout;

            var message = new HttpRequestMessage(HttpMethod.Post, _urlSettleAPIGetTotalAssets);

            // Accept Json
            message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(Constants.MIME_JSON));

            // Form the content to send
            string content = getTotalAssetsContent(blockChainAddress);

            // Add to the message
            message.Content = new StringContent(content);

            // Make API Call
            string sCallRef = "GET TOTAL ASSETS FOR [" + identity + "]";
            Tuple<HttpResponseMessage, string> result = MakeAPICall(client, message, content, sCallRef);
            if (result.Item1 == null)
                return result.Item2; // Error during call

            // Call returned
            HttpResponseMessage response = result.Item1;
            string responseString = result.Item2;

            if (!response.IsSuccessStatusCode)
            {
                msg = "Response Status Code: " + response.StatusCode.ToString();
                logger.Debug(prefix + msg);
                return "Error [" + result.Item2 + "]; " + msg;
            }

            // Else, call returned 200-OK

            logger.Debug(prefix + "Response:\r\n" + responseString + "\r\n");

            return processGetTotalAssetsResponseString(responseString);

        } // end of using...
    }



    public static Tuple<HttpResponseMessage, string> MakeAPICall(HttpClient client, HttpRequestMessage message, string content, string callRef)
    {
        var prefix = "MakeAPICall() - ";
        string msg = "";

        HttpResponseMessage responseMessage;
        string responseString = "";
        try
        {
            responseMessage = client.SendAsync(message).GetAwaiter().GetResult();
            responseString = responseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult();

            return new Tuple<HttpResponseMessage, string>(responseMessage, responseString);
        }
        catch (Exception ex)
        {
            msg = "Exception during call; \r\nBaseMessage:[" + ex.GetBaseException().Message + "]; \r\nMessage:[" + ex.Message + "]";
            logger.Warn(prefix + msg);

            return new Tuple<HttpResponseMessage, string>(null, msg);
        }

    } // end of MakeAPICall()

0 个答案:

没有答案