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.
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();
}
Il y a 2 raisons probables qu'une TaskCanceledException
soit lancée:
Cancel()
sur la CancellationTokenSource
associée au jeton d'annulation avant la fin de la tâche.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.
}
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 ).
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.
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.