HttpClient - A task was cancelled?
There's 2 likely reasons that a TaskCanceledException
would be thrown:
- Something called
Cancel()
on theCancellationTokenSource
associated with the cancellation token before the task completed. - The request timed out, i.e. didn't complete within the timespan you specified on
HttpClient.Timeout
.
My guess is it was a timeout. (If it was an explicit cancellation, you probably would have figured that out.) You can be more certain by inspecting the exception:
try
{
var response = task.Result;
}
catch (TaskCanceledException ex)
{
// Check ex.CancellationToken.IsCancellationRequested here.
// If false, it's pretty safe to assume it was a timeout.
}
HttpClient - task was cancelled - How to get the exact error message?
The default HttpClient.Timeout
value is 100 seconds (00:01:40). If you do a timestamp in your catch
block you will notice that tasks begin to get canceled at exactly that time. Apparently there is a limited number of HTTP requests you can do per second, others get queued. Queued requests get canceled on timeout. Out of all 600k of tasks I personally got only 2500 successful, others got canceled.
I also find it unlikely, that you will be able to run the whole 600000 of tasks. Many network drivers let through high number of requests only for a small time, and reduce that number to a very low value after some time. My network card allowed me to send only 921 requests within 36 seconds and dropped that speed to only one request per second. At that speed it will take a week to complete all the tasks.
If you are able to bypass that limitation, make sure you build the code for 64-bit platform as the app is very hungry for memory.
HttpClient in using statement causes Task cancelled
I know that if the HttpClient is disposed before the asychronous call is finished the Task's state will change to canceled. However since I use an await in: Content = new System.Net.Http.StreamContent(await httpClient.GetStreamAsync(this.filePath)) that should prevent the HttpClient from being disposed off in the middle of the task completion.
But what does that task do? It gets the stream. So, your code ends up with a Stream
that may or may not be completely read when it closes the HttpClient
.
HttpClient
is specifically designed for reuse (and simultaneous use), so I recommend removing the using
completely and moving the HttpClient
declaration to a static
class member. But if you want to close and reopen the clients, you should be able to get it working by reading the stream entirely into memory before closing the HttpClient
.
Handle A task was canceled exception
I'm 99% sure this error is due to a timeout, or the fact you don't actually await your Start
method in MainAsync
I've addressed the timeout issue in the follow code along with some other small changes, which don't necessarily answer your question but hopefully help you nevertheless
class Program
{
private static HttpClient httpClient;
static void Main(string[] args)
{
httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("your base url");
// add any default headers here also
httpClient.Timeout = new TimeSpan(0, 2, 0); // 2 minute timeout
MainAsync().Wait();
}
static async Task MainAsync()
{
await new MyClass(httpClient).StartAsync();
}
}
What I've done here is move the HttpClient
out from your Upload()
method because this class is designed to be reused many times. I've passed the httpClient
object to MyClass
's constructor which you'll see in the next code snippet.
I've also changed MainAsync()
to await
the StartAsync
(renamed from Start to StartAsync because it's convention to suffix async methods) because in your original code MainAsync()
wasn't actually awaiting anything
As I mentioned in the comments, you can change MainAsync().Wait()
to await MainAsync()
if you change Main
to be static async Task Main
, which will require you to change your build language to C# 7.1 or above
public class MyClass
{
private Dictionary<string, string> myDictionary;
private readonly HttpClient httpClient;
public MyClass(HttpClient httpClient)
{
this.httpClient = httpClient;
}
public async Task StartAsync()
{
myDictionary = await UploadAsync("some file path");
}
public async Task<Dictionary<string, string>> UploadAsync(string filePath)
{
byte[] fileContents;
using (FileStream stream = File.Open(filePath, FileMode.Open))
{
fileContents = new byte[stream.Length];
await stream.ReadAsync(fileContents, 0, (int)stream.Length);
}
HttpRequestMessage requestMessage = new HttpRequestMessage();
// your request stuff here
HttpResponseMessage httpResponse = await httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseContentRead, CancellationToken.None);
// parse response and return the dictionary
}
}
In MyClass
I've made the following changes
Added a HttpClient
parameter to the class' constructor, so we can pass our global HttpClient object to this class for it to reuse (which is what we do in MainAsync()
)
As mentioned before, I've renamed Start
and Upload
to StartAsync
and UploadAsync
because it's good practice to suffix async methods with Async
Start
was changed from void
to a Task
because you should only use async void
for event handlers
I changed the way your file is read to also be async, because it seems wasteful to have an async
method that then blocks the CPU waiting for File.ReadAllBytes
to finish. Wherever possible you should use async/await for I/O.
HttpClient c# - A task was canceled at SendASync
You should await both the makeNetworkCallCheckResponseStatusAndExecuteCorrospondingAction
method and the getResponseFromUrlAsync
method. This means that you need to change the return type from void
to Task
:
public static async Task getResponseFromUrlAsync<T>(T payload, string url, Action<string> onSuccess, Action<string> onFailure)
{
string contentType = "application/json";
httpClient = new HttpClient();
httpClient.Timeout = TimeSpan.FromMinutes(30);
HttpRequestMessage requestMsg = new HttpRequestMessage();
requestMsg.RequestUri = new Uri(NetworkCallUrls.baseUri + url);
Utils.debugLog("Url", NetworkCallUrls.baseUri + url);
string auth = "Bearer " + Objects.GlobalVars.GetValue<string>("access_token"); // //"x1VwaR1otS66ZCTlgtv3X9aaSNpDOn"; //
httpClient.DefaultRequestHeaders.Add("Authorization", auth);
requestMsg.Method = HttpMethod.Post;
requestMsg.Content = new StringContent(
Utils.stringifyData(payload),
Encoding.UTF8,
contentType);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT header
await makeNetworkCallCheckResponseStatusAndExecuteCorrospondingAction(requestMsg, onSuccess, onFailure, progressBarStatus)
.ConfigureAwait(false);
}
internal static void disposeConnection(HttpClient httpClient)
{
httpClient.Dispose();
httpClient = null;
}
private static async Task makeNetworkCallCheckResponseStatusAndExecuteCorrospondingAction(
HttpRequestMessage requestMsg, Action<string> onSuccess,
Action<string> onFailure, Action<bool> progressBarStatus)
{
Utils.debugLog("IN MAKE NETWORK CALL 1");
HttpResponseMessage response = await httpClient.SendAsync(requestMsg).ConfigureAwait(false);
Utils.debugLog("IN MAKE NETWORK CALL 2");
ResponseStatus responseStatus = checkResponseStatusAndExecuteActionAccordinglyAsync(response);
Utils.debugLog("IN MAKE NETWORK CALL 3");
if (responseStatus.isSuccess)
{
Utils.debugLog("IN MAKE NETWORK CALL 4");
string responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
Utils.debugLog("IN MAKE NETWORK CALL 5");
onSuccess(responseString);
Utils.debugLog("IN MAKE NETWORK CALL 6");
}
else
{
Utils.debugLog("IN MAKE NETWORK CALL 7");
onFailure(responseStatus.failureResponse);
Utils.debugLog("IN MAKE NETWORK CALL 8");
}
Utils.debugLog("IN MAKE NETWORK CALL 9");
disposeConnection(httpClient);
Utils.debugLog("IN MAKE NETWORK CALL 10");
}
...and await
the method when you call it:
await getResponseFromUrlAsync<..>(...);
Related Topics
Does C# Optimize the Concatenation of String Literals
How to Parse Hex Values into a Uint
Cancellation Token in Task Constructor: Why
How to Print the Current Stack Trace in .Net Without Any Exception
How to Fix a Opacity Bug with Drawtobitmap on Webbrowser Control
Why Do These Division Equations Result in Zero
Recursively Get Properties & Child Properties of a Class
How to Connect to Database from Unity
Get All Inherited Classes of an Abstract Class
Difference Between "\N" and Environment.Newline
Is There a Downside to Adding an Anonymous Empty Delegate on Event Declaration
Change C# Dllimport Target Code Depending on X64/X86
Hide Tabcontrol Buttons to Manage Stacked Panel Controls
What Characters Are Allowed in C# Class Name