HttpClient: un’attività è stata cancellata?

Funziona bene quando una o due attività generano comunque un errore “Un’attività è stata annullata” quando sono elencate più attività.

inserisci la descrizione dell'immagine qui

List allTasks = new List(); allTasks.Add(....); allTasks.Add(....); Task.WaitAll(allTasks.ToArray(), configuration.CancellationToken); private static Task HttpClientSendAsync(string url, object data, HttpMethod method, string contentType, CancellationToken token) { HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, url); HttpClient httpClient = new HttpClient(); httpClient.Timeout = new TimeSpan(Constants.TimeOut); if (data != null) { byte[] byteArray = Encoding.ASCII.GetBytes(Helper.ToJSON(data)); MemoryStream memoryStream = new MemoryStream(byteArray); httpRequestMessage.Content = new StringContent(new StreamReader(memoryStream).ReadToEnd(), Encoding.UTF8, contentType); } return httpClient.SendAsync(httpRequestMessage).ContinueWith(task => { var response = task.Result; return response.Content.ReadAsStringAsync().ContinueWith(stringTask => { var json = stringTask.Result; return Helper.FromJSON(json); }); }).Unwrap(); } 

Ci sono 2 probabili motivi per cui viene lanciata una TaskCanceledException :

  1. Qualcosa chiamato Cancel() sul CancellationTokenSource associato al token di cancellazione prima del completamento dell’attività.
  2. La richiesta è scaduta, ovvero non è stata completata entro il periodo di tempo specificato su HttpClient.Timeout .

La mia ipotesi è che era un timeout. (Se si trattava di una cancellazione esplicita, probabilmente l’avresti capito.) Puoi essere più sicuro controllando l’eccezione:

 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. } 

Mi sono imbattuto in questo problema perché il mio metodo Main() non era in attesa del completamento Task myTask prima di essere restituito, quindi l’ Task myTask veniva annullata quando il mio programma di console si Task myTask .

La soluzione era chiamare myTask.GetAwaiter().GetResult() in Main() (da questa risposta ).

Un’altra possibilità è che il risultato non sia atteso dal lato del cliente. Ciò può accadere se uno qualsiasi metodo nello stack di chiamate non utilizza la parola chiave await per attendere il completamento della chiamata.