web-dev-qa-db-fra.com

HttpClient - Une tâche a été annulée?

Cela fonctionne bien lorsque vous avez une ou deux tâches, mais génère une erreur "Une tâche a été annulée" lorsque plusieurs tâches sont répertoriées.

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();
}
132

Il y a 2 raisons probables qu'une TaskCanceledException soit lancée:

  1. Quelque chose appelé Cancel() sur la CancellationTokenSource associée au jeton d'annulation avant la fin de la tâche.
  2. La demande a expiré, c’est-à-dire qu’elle n’a pas abouti dans les délais spécifiés dans HttpClient.Timeout.

Je suppose que c'était un délai d'attente. (S'il s'agissait d'une annulation explicite, vous l'auriez probablement compris.) Vous pouvez être plus certain en inspectant l'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.
}
190
Todd Menier

J'ai rencontré ce problème car ma méthode Main() n'attendait pas que la tâche soit terminée avant de retourner. Le Task<HttpResponseMessage> myTask était donc annulé à la fermeture de mon programme de console.

La solution consistait à appeler myTask.GetAwaiter().GetResult() dans Main() (à partir de cette réponse ).

11
Ben Hutchison

Une autre possibilité est que le résultat ne soit pas attendu du côté client. Cela peut arriver si l'une des méthodes de la pile d'appels n'utilise pas le mot-clé wait pour attendre la fin de l'appel.

8
Manish

Une autre raison peut être que si vous exécutez le service (API) et mettez un point d'arrêt dans le service (et que votre code est bloqué à un point d'arrêt (par exemple, la solution Visual Studio affiche Debugging au lieu de En cours d'exécution ) ). puis en touchant l'API à partir du code client. Donc, si le code de service est en pause sur un point d'arrêt, il suffit d'appuyer sur F5 dans VS.

0
vivek nuna