Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 调用httpClient.GetAsync()时未能发送任何数据,有时捕获TaskCanceledException_C#_.net_Async Await_Fiddler_Dotnet Httpclient - Fatal编程技术网

C# 调用httpClient.GetAsync()时未能发送任何数据,有时捕获TaskCanceledException

C# 调用httpClient.GetAsync()时未能发送任何数据,有时捕获TaskCanceledException,c#,.net,async-await,fiddler,dotnet-httpclient,C#,.net,Async Await,Fiddler,Dotnet Httpclient,我开发了C#.net 4.6.1应用程序(这是Windows服务应用程序)。在应用程序中,我使用HttpClient与后端API进行通信。随着时间的推移,应用程序不会将请求发送到后端(TaskCanceledException被捕获) 下面是此异常的堆栈跟踪 System.Threading.Tasks.TaskCanceledException·任务已取消 公共静态类TestHttpClient { 私有静态httpclientu HttpClient; 公共静态void Init() { S

我开发了C#.net 4.6.1应用程序(这是
Windows服务应用程序
)。在应用程序中,我使用HttpClient与后端API进行通信。随着时间的推移,应用程序不会将请求发送到后端(TaskCanceledException被捕获)

下面是此异常的堆栈跟踪

System.Threading.Tasks.TaskCanceledException·任务已取消

公共静态类TestHttpClient
{
私有静态httpclientu HttpClient;
公共静态void Init()
{
ServicePointManager.SecurityProtocol |=(SecurityProtocolType.Ssl3 |
SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 |
SecurityProtocolType.Tls);
ServicePointManager.DefaultConnectionLimit=10;
_httpClient=CreateHttpClient();
}
私有静态HttpClient CreateHttpClient()
{
HttpClient=新的HttpClient();
client.DefaultRequestHeaders.Authorization=新的AuthenticationHeaderValue(“令牌…”);
client.DefaultRequestHeaders.Accept.Add(新的MediaTypeWithQualityHeaderValue(“应用程序/json”);
client.Timeout=TimeSpan.From毫秒(10000);
返回客户;
}
公共静态异步任务GetMyClassResponse()
{
HttpResponseMessage响应=等待GetRequestAsync(“https://api.example.com/test");
返回wait wait ParseToMyClassResponse(response);
}
专用静态异步任务GetRequestAsync(字符串url)
{
尝试
{
返回wait_httpClient.GetAsync(新Uri(url));
}
捕获(TaskCanceledException)
{
返回新的HttpResponseMessage(HttpStatusCode.RequestTimeout);
}
}
私有静态异步任务ParseToCyclassResponse(HttpResponseMessage响应),其中T:MyClassResponse,new()
{
T-myClassResponse;
尝试
{
string content=wait response.content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
myClassResponse=JsonConvert.DeserializeObject(内容);
}
捕获(例外情况除外)
{
myClassResponse=newt();
}
response.Dispose();
返回myClassResponse;
}
}
我做错了什么

为什么
Fiddler
显示
“客户端收到已建立连接的通知后,无法发送任何数据”
消息

  • 首先,替换这个
  • static void Main(字符串[]args)
    {
    //我也尝试过不使用Task.Run(),即MyClass MyClass=GetAsync().Result;
    MyClass MyClass=Task.Run(()=>GetAsync().Result).Result;
    }
    
    带威士忌

    static async Task Main(字符串[]args)
    {
    MyClass MyClass=await GetAsync();
    控制台。WriteLine(“全部完成”);
    Console.ReadKey();
    }
    
  • HttpResponseMessage
    IDisposable
    ,请正确使用
  • 公共静态异步任务GetMyClassResponse()
    {
    使用(HttpResponseMessage response=await GetRequestAsync(“https://api.example.com/test"))
    {
    返回wait wait ParseToMyClassResponse(response);
    }
    }
    
    并从
    ParseToMyClassResponse

  • 为了进行额外的测试,我重写了代码以使其更简单
  • 公共类程序
    {
    私有只读静态HttpClient=新HttpClient();
    静态异步任务主(字符串[]args)
    {
    client.DefaultRequestHeaders.Authorization=新的AuthenticationHeaderValue(“令牌…”);
    client.DefaultRequestHeaders.Accept.Add(新的MediaTypeWithQualityHeaderValue(“应用程序/json”);
    client.Timeout=TimeSpan.From毫秒(10000);
    ServicePointManager.DefaultConnectionLimit=10;
    尝试
    {
    MyClassResponse MyClassResponse=等待GetAPIResponseAsync(“https://api.example.com/test");
    MyClass MyClass=MyClass.Create(myClassResponse);
    }
    捕获(例外情况除外)
    {
    控制台写入线(例如消息);
    Console.WriteLine();
    控制台写入线(例如StackTrace);
    }
    控制台。WriteLine(“全部完成”);
    Console.ReadKey();
    }
    专用静态异步任务GetAPIResponseAsync(字符串url)
    {
    使用(httpresponsemessageresponse=wait client.GetAsync(url,HttpCompletionOption.ResponseHeadersRead))
    {
    response.EnsureSuccessStatusCode();
    string content=wait response.content.ReadAsStringAsync();
    返回JsonConvert.DeserializeObject(内容);
    }
    }
    }
    
    测试这个版本

    此外,不建议在代码中更改
    SecurityProtocol
    ,因为这会使应用程序易受攻击,请改用默认设置。如果要更改测试的TLS版本


    已更新

    我已经看了来源

    这是一种糟糕的并发编程。在任务和块任务中运行异步函数,并在其中执行异步函数,同时块当前线程

    Task<PassResponse> task = Task.Run(() => GetPass(scannedValue).Result);
    PassResponse passResponse = task.Result;
    

    再试一次

    让我们改变这一行,以避免可能的死锁

    returnawait\u httpClient.GetAsync(新Uri(url));
    

    return await\u httpClient.GetAsync(新Uri(url)).ConfigureAwait(false);
    
    这个呢

    string content=wait response.content.ReadAsStringAsync();
    

    string content=await response.content.ReadAsStringAsync().ConfigureAwait(false);
    
    您不应该再使用
    SecurityProtocolType.Ssl3
    。SSLv3严重不安全且过时。大多数服务器甚至不再支持SSLv3客户端hello.Hi@Robert。谢谢你的快速回复。我们有一个
    System.Net.WebException:请求w
    
    class Program
    {
      static void Main(string[] args)
      {
        // I Tried also without  Task.Run() i.e. MyClass myClass = GetAsync().Result; 
        MyClass myClass = Task.Run(() => GetAsync().Result).Result ;
      }
            
      private static async Task<MyClass> GetAsync()
      {
        // I Tried also without .ConfigureAwait(false)
         MyClassResponse myClassResponse = await TestHttpClient.GetMyClassResponse().ConfigureAwait(false);
        return MyClass.Create(myClassResponse);
      }
    }
    
    public static class TestHttpClient
    {
       private static HttpClient _httpClient;
       
       public static void Init()
       {
          ServicePointManager.SecurityProtocol |= (SecurityProtocolType.Ssl3 | 
                    SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | 
                                                 SecurityProtocolType.Tls);
          ServicePointManager.DefaultConnectionLimit = 10;
         _httpClient = CreateHttpClient();
       }
    
       private static HttpClient CreateHttpClient()
       {
          HttpClient client = new HttpClient();
          client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("token .....");
          client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
          client.Timeout = TimeSpan.FromMilliseconds(10000);
          return client;
        }
    
       public static async Task<MyClassResponse> GetMyClassResponse()
       {
          HttpResponseMessage response = await GetRequestAsync("https://api.example.com/test");
          return await ParseToMyClassResponse<MyClassResponse>(response);
       }
     
        private static async Task<HttpResponseMessage> GetRequestAsync(string url)
       {
            try
            {
               return await _httpClient.GetAsync(new Uri(url));
             }
             catch (TaskCanceledException)
             {
              return new HttpResponseMessage(HttpStatusCode.RequestTimeout);
             }
        }
    
        private static async Task<T> ParseToMyClassResponse<T>(HttpResponseMessage response) where T : MyClassResponse, new()
            {
                T myClassResponse;
                try
                {
                    string content = await response.Content.ReadAsStringAsync();
                    response.EnsureSuccessStatusCode();
                    myClassResponse = JsonConvert.DeserializeObject<T>(content);
                               }
                catch (Exception ex)
                {
                    myClassResponse = new T();
                }
    
                response.Dispose();
                return myClassResponse;
            }
    }
    
    
    Task<PassResponse> task = Task.Run(() => GetPass(scannedValue).Result);
    PassResponse passResponse = task.Result;
    
    PassResponse passResponse = GetPass(scannedValue).Result;