C# 调用httpClient.GetAsync()时未能发送任何数据,有时捕获TaskCanceledException
我开发了C#.net 4.6.1应用程序(这是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
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;