2015-03-21 20 views
84

Funziona bene quando una o due attività generano tuttavia un errore "Un'attività è stata annullata" quando sono elencate più attività.HttpClient - Un'attività è stata annullata?

enter image description here

List<Task> allTasks = new List<Task>(); 
allTasks.Add(....); 
allTasks.Add(....); 
Task.WaitAll(allTasks.ToArray(), configuration.CancellationToken); 


private static Task<T> HttpClientSendAsync<T>(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<T>(json); 
     }); 
    }).Unwrap(); 
} 
+0

Che cosa dice l'Eccezione interna? – RagtimeWilly

+0

Perché prendi un 'CancellationToken' come parametro e non lo usi? –

risposta

128

Ci sono 2 possibili ragioni per cui un TaskCanceledException sarebbe stato gettato:

  1. qualcosa chiamato Cancel() sul CancellationTokenSource associato con il token cancellazione prima l'operazione completata.
  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 fosse una revoca esplicita, probabilmente avrebbe capito che fuori.) Si può essere più certi ispezionando 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. 
} 
+3

Allora, qual è una possibile soluzione? Ho un problema simile. http://stackoverflow.com/questions/36937328/get-asp-net-mvc5-webapi-token-fails-sometimes?noredirect=1#comment61434357_36937328 –

+20

@Dimi - questo è piuttosto vecchio, ma la soluzione che ho usato è stata quella di impostare la proprietà Timeout a un valore più grande: 'httpClient.Timeout = TimeSpan.FromMinutes (30)' – RQDQ

+1

@RQDQ, tu l'uomo, amico! Non usare il costruttore ha risolto il problema per me. Nel mio caso specifico, volevo un timeout in millisecondi. L'utilizzo di 'TimeSpan.FromMilliseconds (Configuration.HttpTimeout)' rispetto a 'new TimeSpan (Configuration.HttpTimeout)' ha funzionato bene. Grazie! –

5

mi sono imbattuto in questo problema perché il mio metodo Main() non era in attesa per il compito da completare prima di tornare, quindi lo Task<HttpResponseMessage> myTask veniva cancellato quando il mio programma di console si chiudeva.

La soluzione era chiamare myTask.GetAwaiter().GetResult() in Main() (da this answer).

+0

Grazie mille, hai risparmiato molto del mio tempo. – RaM

2

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

+0

Grazie Manish, questo ha aiutato a correggere la mia eccezione. – Gunarathinam

Problemi correlati