web-dev-qa-db-fra.com

HttpClient - la tâche a été annulée - Comment obtenir le message d'erreur exact?

J'ai le code de test suivant. J'obtiens toujours l'erreur "La tâche a été annulée" après avoir bouclé 316934 ou 361992 fois.

Si je ne me trompe pas, il y a deux raisons possibles pour lesquelles la tâche a été annulée a) HttpClient a obtenu un délai d'attente ou b) trop de tâches dans la file d'attente et certaines tâches ont expiré.

Je n'ai pas pu trouver la documentation sur la limitation de la mise en file d'attente des tâches. Et j'ai essayé de créer plus de 500 000 tâches et aucun délai d'attente. Je suppose que la raison "b" n'est peut-être pas juste.

Q1. Y a-t-il une autre raison pour laquelle j'ai manqué?

Q2. Si c'est à cause du délai d'expiration HttpClient, comment puis-je obtenir le message d'exception exact au lieu de l'exception "TaskCancellation".

Q3. Quelle serait la meilleure façon de le réparer? Dois-je présenter le throttler?

Merci!

var _httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "text/html,application/xhtml+xml,application/xml");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Encoding", "gzip, deflate");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Charset", "ISO-8859-1");

int[] intArray = Enumerable.Range(0, 600000).ToArray();

var results = intArray                
    .Select(async t => {

        using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, "http://www.google.com")) {
            log.Info(t);

            try {

                var response = await _httpClient.SendAsync(requestMessage);
                var responseContent = await response.Content.ReadAsStringAsync();

                return responseContent;
            }
            catch (Exception ex) {
                log.ErrorException(string.Format("SoeHtike {0}", Task.CurrentId), ex);
            }
            return null;
        }
    });

Task.WaitAll(results.ToArray());

Console.ReadLine();

Voici l'étape pour reproduire le problème.

  1. Créez un projet de console dans VS 2012.

  2. Veuillez copier et coller mon code dans Main.

  3. Placez le point d'arrêt à cette ligne "log.ErrorException (string.Format (" SoeHtike {0} ", Task.CurrentId), ex);"

Exécutez le programme en mode débogage. Attendez quelques minutes. (peut-être 5 minutes?) Je viens de tester mon code et j'ai eu l'exception après 3 minutes. Si vous avez un violoneux, vous pouvez surveiller les demandes afin de savoir si le programme est toujours en cours d'exécution ou non.

N'hésitez pas à me faire savoir si vous ne pouvez pas reproduire le problème.

51
Michael Sync

Le défaut HttpClient.Timeout la valeur est de 100 secondes (00:01:40). Si vous effectuez un horodatage dans votre bloc catch, vous remarquerez que les tâches commencent à être annulées à ce moment précis. Apparemment, il y a un nombre limité de requêtes HTTP que vous pouvez faire par seconde, d'autres sont mises en file d'attente. Les demandes en file d'attente sont annulées à l'expiration du délai. Sur les 600 000 tâches, personnellement, je n'ai réussi que 2 500, d'autres ont été annulées.

Je trouve également peu probable que vous puissiez exécuter l'ensemble des 600 000 tâches. De nombreux pilotes de réseau ne laissent passer un nombre élevé de demandes que pendant une courte période et réduisent ce nombre à une valeur très faible après un certain temps. Ma carte réseau m'a permis d'envoyer seulement 921 demandes en 36 secondes et a réduit cette vitesse à une seule demande par seconde. À cette vitesse, il faudra une semaine pour terminer toutes les tâches.

Si vous êtes en mesure de contourner cette limitation, assurez-vous de créer le code pour la plate-forme 64 bits car l'application a très faim de mémoire.

64
Dmitri Trofimov

Ne supprimez pas l'instance de HttpClient que vous utilisez. Bizarre mais corrigé pour moi ce problème.

34
abatishchev

je voulais juste partager J'ai eu un code similaire pour tester la charge de nos serveurs, et c'est une forte probabilité que vos demandes expirent. Vous pouvez définir le délai d'expiration de votre demande http sur max et voir si cela change quelque chose pour vous. J'ai essayé de frapper nos serveurs en créant divers threads. Et cela augmentait les hits, mais ils finiraient tous par expirer. Et vous ne pouvez pas non plus définir de délai lorsque vous les frappez sur un autre thread.

1
Andy Khatter