2009-11-21 4 views
2

Analyser le code ci-dessous dans l'action par Fiddler, je réalise que l'utilisation des extensions parallèles que je peux obtenir au maximum 2 demandes sortantes:Comment obtenir le maximum de demandes sortantes lors de la parellellisation d'appels asynchrones?

new string[] 
    { 
     "http://stackoverflow.com", 
     "http://superuser.com", 
     "http://serverfault.com", 
     "http://stackexchange.com" 
    } 
    .AsParallel() 
    .Select(a => HttpWebRequest.Create(a).GetResponse()) 
    .ToArray() 
    ; 

Quelle méthode dois-je utiliser pour maximiser le nombre de demandes sortantes?

Répondre

2

Ce code exécute les 6 requêtes HTTP en parallèle sur ma machine selon Wireshark:

var urls = new string[] 
{ 
    "http://stackoverflow.com", 
    "http://superuser.com", 
    "http://serverfault.com", 
    "http://stackexchange.com", 
    "http://www.howtogeek.com", 
    "http://meta.stackoverflow.com" 
}; 

var reqs = urls.Select<string, WebRequest>(HttpWebRequest.Create).ToArray(); 
var iars = reqs.Select(req => req.BeginGetResponse(null, null)).ToArray(); 
var rsps = reqs.Select((req, i) => req.EndGetResponse(iars[i])).ToArray(); 

Fondamentalement, il crée une WebRequest pour chaque URL, appelle BeginGetResponse sur chaque puis appelle EndGetResponse pour chacun avec le IAsyncResult La documentation indique que BeginGetResponse utilise The Managed Thread Pool pour effectuer la requête HTTP.

+0

Maintenant que je l'ai testé votre code, j'ai réalisé qu'il atteint un maximum de 7 requêtes simultanées sur ma machine (pour les tableaux d'entrée plus grandes). –

0

ServicePointManager.DefaultConnectionLimit

http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.defaultconnectionlimit.aspx

Dans votre cas, il a mis à 4.

+0

est-ce pas la limite de connexion persistante par serveur? – dtb

+0

Je l'ai essayé, et ça n'a pas marché. Ce qui est remarqué que si je ne jetez pas mes connexions mon application s'arrête quand il atteint le nombre de connexions spécifiées sur ServicePointManager.DefaultConnectionLimit non légué –

+0

Il ne fonctionne pas parce que la limite par défaut est bien plus qu'un simple 4. –

3

Par défaut, le PFX crée ce nombre de threads que votre numéro de CPU de cœurs. C'est pourquoi vous avez seulement deux demandes. Utilisez la classe Task de PFX et exécutez-les tous via Task.WaitAll. (J'espère que ma conjecture est correcte.)

EDIT: Exemple

var tasks = servers.Select(Task.Create(() => GetResponseCallHere(...))).ToArray(); 
Task.WaitAll(tasks); 
+0

est-ce pas PFX construit sur 'Task'? Avez-vous un lien vers docs pour confirmer que le nombre de threads est défini sur le nombre de processeurs/cœurs dans PFX? – dtb

+0

TaskManagerPolicy par défaut est créé lorsqu'une boucle foreach parallèle est démarrée. Et voici le texte de ParallelExtensions_Jun08CTP_Help: « IdealProcessors - Retourne le nombre idéal de processeur à utiliser pour l'exécution des tâches sur ce TaskManagerPolicy La valeur par défaut est égal au nombre réel de processeurs sur le système. ». –

+0

Et voici la preuve lien au forum PFX: http://social.msdn.microsoft.com/Forums/fr-FR/parallelextensions/thread/5b1383ed-27c1-40ba-8d98-b5ab5aa762ec –

0

Notez que dans la question je la version sychronous de la méthode BeginGetResponse. Ce que j'ai trouvé jusqu'à présent, c'est que la seule façon de maximiser la requête sortante est d'utiliser la version asynchrone de la méthode. Mais cette approche donne de nouveaux problèmes, à savoir:

  1. Vous devez diviser votre logique de l'appelant dans deux méthodes
  2. Il est difficile de garder une trace si tous les appels sortants ont été achevés.
  3. Il est difficile de gérer les exceptions.
  4. Si le nombre de tâches à exécuter dépasse la taille du pool de fil, alors Dieu seul sait ce qui se passe

    new string[] 
    { 
        "http://stackoverflow.com", 
        "http://superuser.com", 
        "http://serverfault.com", 
        "http://stackexchange.com" 
    } 
    .Select(a => HttpWebRequest.Create(a).BeginGetResponse(callback, null)) 
    .ToArray(); 
    
+0

parallèle Avez-vous essayé ceci sans .AsParallel()? Je m'attendrais à peu de différence. –

+0

@Henk vous avez raison –

Questions connexes