首页 > 解决方案 > 当请求需要很长时间时,net core 控制台应用程序 C# HttpClient 挂起

问题描述

控制台 App Net Core 3.0

我正在向 Dynamic CRM Api 发送批处理请求,基本上我读取了一个文件夹来查找由另一个进程(Nodejs)生成的文本文件,这些文件具有请求内容,然后我遍历这些文件,将文本内容作为字符串和发送。问题是当任何这些文件的内容更大(500kb +)时问题是当请求需要更长的时间(5分钟或更长时间)然后HttpClient.SendAsync开始但从未完成时,系统挂在那里,我知道发送是成功的原因我签入 api 并应用更改,但自动化过程在那里停止,我必须终止应用程序。如果内容不是那么大,那么一切都会顺利进行。

最令人沮丧的是没有任何错误或反馈导致我找到任何解决方案或解决方法。

重要细节:

我认为这不应该是死锁,因为链中的每个异步调用都在等待,sendasync 也设置为 ConfigureAwait(false)。没有 .Result,没有 Wait() 或任何其他阻塞操作被调用。

我不会通过为每个请求创建一个 HttpClient 实例来耗尽网络套接字,我正在使用IHttpClientFactory将 httpClient 实例作为 Singleton 分派。问题发生在它遇到的第一个长内容请求中。

更新 我意识到问题与有效负载大小无关,但随着请求完成所需的时间,我注意到 200kb 或更少的文件挂起,因为服务器需要超过 8 分钟才能完成。

编码:

        HttpRequestMessage GetRequest(string batchId, string requestBody)
        {
            var request = new HttpRequestMessage(HttpMethod.Post,"$batch");
            request.Headers.Add("OData-MaxVersion", "4.0");
            request.Headers.Add("OData-Version", "4.0");
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            request.Content = GetContent(batchId, requestBody);

            return request;
        }

         StringContent GetContent(string batchId, string requestBody)
        {
            var content = new StringContent(requestBody);
            content.Headers.Remove("Content-Type");
            content.Headers.Add("Content-Type", $"multipart/mixed;boundary=batch_{batchId}");

            return content;
        }
        string GetRequestBody(string file)
        {
            var requestBody = "";
            using (var sr = new StreamReader(file))
            {
                requestBody = sr.ReadToEnd();
            }

            return requestBody;
        }

        private async Task<HttpResponseMessage> SendRequest(string batchId, string file)
        {    
            // this call is awaited since the access token may expire then is necessary to request a new one
            var httpClient = await _httpClientBuilder.BuildHttpClient().ConfigureAwait(false);

             var requestBody = GetRequestBody(file); // Here I read the text from the file

            using(var request = GetRequest(batchId, requestBody)){
              using(var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)){ // after this call nothing is executed
                  if (response.IsSuccessStatusCode)
                  {
                      CustomConsole.Success("({0})Successfully Sent batch: {1}", response.StatusCode, batchId);
                      File.Delete(file);
                  }
                  else
                  {
                      CustomConsole.Error("({0}) Error sending batch: {1}", response.StatusCode, batchId);
                      var responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                      CustomConsole.Info("Response Body:");
                      CustomConsole.Info("{0}",responseBody);
                  }
       

                  return response;   
                }
            }
           
        }

标签: c#.net-coreconsole-applicationhttpclient

解决方案


推荐阅读