I developed C# .net 4.6.1 application (this is Windows Service Application
). In the application I use HttpClient for communicate with our backend API. Over time the application not sending the request to our backend (TaskCanceledException is catched).
Here is stacktrace of this exception
System.Threading.Tasks.TaskCanceledException · A task was cancelled.
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
TestHttpClient+<GetRequestAsync>d__20.MoveNext()
This issue solves in two reason
- after restart application
- When attempt the same request repeatedly
I investigated this issue using Fiddler
, when an exception occurs and in normal condition
In normal mode fiddler shows 2 requests
- Result=200, Protocol=HTTP, Host = Tunnel to, Url = api.example.com:443
in SyntaxView tab: A SSLv3-compatible ClientHello handshake was found. Fiddler extracted the parameters below.
- Result=200, Protocol=HTTPS, Host = api.example.com, Url = /test
In failed mode Fiddler shows only 1 requst
- Result=200, Protocol=HTTP, Host = Tunnel to, Url = api.example.com:443,
in SyntaxView tab: After the client received notice of the established CONNECT, it failed to send any data
Here is the snippet of our code.
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;
}
}
What am I doing wrong?
Why Fiddler
shows "After the client received notice of the established CONNECT, it failed to send any data"
message.