HttpWebRequest - puis-je faire plusieurs appels à la sametime à partir de plusieurs threads
- Je utiliser HttpWebRequest de créer des demandes de pages web, de les analyser.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address);
puis si plusieurs threads appel
HttpWebResponse response = (HttpWebResponse)request.GetResponse()
dans le même temps, chacun doit-il obtenir sa propre réponse ou est-il possible pour le thread 2 pour obtenir la réponse pour thread7 par exemple?
Obs: l'adresse est la même pour tous les threads, uniquement l'après changement des paramètres de
public class CheckHelper
{
public string GetPOSTWebsiteResponse(string WebAddress, string year)
{
StringBuilder QuerryData = new StringBuilder();
String ResponseString;
QuerryData.Append("forYear"+ "=" + year);
#region build request
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(WebAddress);
//Set the Method property of the request to POST
request.Method = "POST";
NameValueCollection headers = request.Headers;
Type t = headers.GetType();
PropertyInfo p = t.GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
p.SetValue(headers, false, null);
byte[] byteArray = Encoding.UTF8.GetBytes(QuerryData.ToString());
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
#endregion
//Get the request stream.
using (Stream requestStream = request.GetRequestStream())
{
//Write the data to the request stream.
requestStream.Write(byteArray, 0, byteArray.Length);
//Close the Stream object.
}
#region get response
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
//Get the stream containing content returned by the server.
using (var responseStream = response.GetResponseStream())
{
//Open the stream using a StreamReader for easy access.
using (StreamReader responseReader = new StreamReader(responseStream))
{
//Read the content.
ResponseString = responseReader.ReadToEnd();
}
}
}
#endregion
return ResponseString;
}
}
c'est la façon dont j'utilise la méthode:
Dictionary<int, Thread> threads=new Dictionary<int,Thread>();
foreach (var year in AvailableYears)
{
threads[year] = new Thread(delegate()
{
var client=new CheckHelper();
string response=client.GetPOSTWebsiteResponse("http://abc123.com", year.ToString())
//The thread for year 2003 may get the response for the year 2007
responsesDictionary[year]=response;
});
threads[year].Start();
}
//this is to force the main thread to wait until all responses are received:
foreach(var th in threads.Values){
th.Join(10000);
}
S'il vous plaît dites-moi où je me trompe? Comment dois-je changer le code? S'il vous plaît aider, je ne peux pas trouver quelque chose d'utile sur le web!
Êtes-vous de la création de la demande dans le même thread qui est de la réception de la réponse? Si oui, alors vous ne devriez pas avoir un problème avec les réponses de se mêler. Pouvez-vous mettre à jour votre question pour être plus précis? Merci!
oui. GetPOSTWebsiteResponse méthode est de faire les deux httprequest et httpresponse. Yhis méthode est appelée par chaque thread separatelly. Je n'utilise pas d'autres threads dans une méthode que celles que vous voyez dans l'exemple de code. Espère que je suis clair, si non, merci de demander
Quelle est la version de .net vous aide?
.Net framework 4
vous devriez être en utilisant les méthodes asynchrones plutôt que de frai de threads. C'est principalement une I/O bound opération, la ponte des threads n'est pas vraiment nécessaire. Deuxièmement, si vous avez modifié le DefaultConnection limite, vous n'obtenez pas plus de 2 threads en même temps depuis la limite par défaut est de 2 par domaine et vous allez depuis le même domaine...
oui. GetPOSTWebsiteResponse méthode est de faire les deux httprequest et httpresponse. Yhis méthode est appelée par chaque thread separatelly. Je n'utilise pas d'autres threads dans une méthode que celles que vous voyez dans l'exemple de code. Espère que je suis clair, si non, merci de demander
Quelle est la version de .net vous aide?
.Net framework 4
vous devriez être en utilisant les méthodes asynchrones plutôt que de frai de threads. C'est principalement une I/O bound opération, la ponte des threads n'est pas vraiment nécessaire. Deuxièmement, si vous avez modifié le DefaultConnection limite, vous n'obtenez pas plus de 2 threads en même temps depuis la limite par défaut est de 2 par domaine et vous allez depuis le même domaine...
OriginalL'auteur Ryan | 2011-02-19
Vous devez vous connecter pour publier un commentaire.
Pour être honnête, je ne crois pas que le multi-threading, vous êtes en essayant de faire va vous recevoir tout de gains de performance. Et de voir qu'il n'y a pas de seuil pour le nombre de threads que vous pourriez être la création d'ici le potentiel pour le pire rendement qu'un seul thread (séquentiel) opération existe.
La situation idéale est que vous avez un travail asynchrone flux. lorsque la boucle est quelque chose comme ceci:
GetAsyncRequest
MakeAsyncRequest
ReceiveResponseAsync
ProcessResponse
WaitForAllRequestProcessingToComplete(En Option)
Tels que le résultat de chaque étape se nourrit dans la prochaine (si il y a un résultat) et à la prochaine. Et vous traitez les réponses dès que vous les recevez, plutôt que l'accumulation (joindre/bloquer) toutes les réponses avant de continuer à les traiter. Ce genre de chose peut être fait facilement avec les Tâches et les ContinueWith .NET 4.0 et voir que vous avez de l'utiliser .NET 4.0 j'aimerais vous suggérons fortement de le faire, comme décrit ci-dessus.
Mais, si vous n'êtes pas en mesure de convertir votre traitement dans un async flux de travail, alors...
La méthode indiquée ci-dessous est la méthode qui fait l'appel à l'Url et renvoie une réponse. La méthode utilise les appels Asynchrones mais bloque depuis votre conception semble être en tant que tel.
Vous souhaitez appeler comme ceci:
Voir si cela fonctionne pour vous.
Si vous avez vraiment besoin de multi-threaded capacité, bien sûr, vu que vous avez frapper un seul site, il faudrait mesurer la performance des prestations depuis le site doit être en mesure de gérer l'assaut des demandes et sur le client le coût de la création de threads, uniquement pour faire quelques I/O bound tâche pourrait être trop coûteux et à la fin avec pas de gains de performance.
D'ailleurs, sans réglage de DefaultConnectionLimit dans le ServicePointManager, vous ne serez jamais plus de 2 threads soit car vous allez à l'encontre de l'un de domaine et la limite par défaut est de 2 threads par domaine.
Je collerais avec le code que j'ai présenté et si il y a un problème de performance alors je le regarde faire d'une autre manière.
Edit:
lors de l'utilisation d'e/S Asynchrone vous n'êtes pas à l'aide de threads de travail, mais I/O fil. Donc, fondamentalement, vous ne voulez pas utiliser QueueUserWorkItem (pour créer des threads) ou vous n'êtes pas créer des threads de vous-même.
Le code que j'ai présenté est à l'aide d'e/S Asynchrone et s'apprête à exécuter de multiples demandes simutaneously et aussi vite que possible.
Pour la boucle (dans le deuxième exemple de code) va finir presque immédiatement, même si, dans l'exemple il fait une boucle pour 100 itérations, et puis attendre que toutes les demandes d'e/S à la fin. Le pool de threads et OS pour gérer l'exécution de l'I/O un emploi le plus rapidement et le plus vite possible. En fait, parce que ces emplois sont I/O bound, vous ne verrez pas votre utilisation de l'UC aller jusqu'soit (sauf si vous êtes en train de faire en cpu, travail par la suite).
Il suffit de jouer avec le ServiceManager.DefaultConnectionLimit pour obtenir plus d'accélération en cas de besoin. Notez que cela affecte le service (le serveur), car si vous faites beaucoup de requêtes simultanées que le serveur vous appelez devient très chargé et qui ne peut pas être quelque chose que vous voulez. C'est donc un équilibre dont vous avez besoin de faire la grève.
Après l'appel à la Tâche.WaitAll, vous pouvez parcourir vos tâches de collecte et d'obtenir les résultats de chaque tâche à l'aide de la syntaxe indiquée dans la ligne de commentaire dans le code.
J'ai édité ma réponse pour plus d'informations et répondre à votre question.
merci pour le partage
ServicePointManager.DefaultConnectionLimit = noOfThread;
il m'a vraiment aidé, j'ai été appelerBeginGetResponse
de la demande multiple d'un même URL simultanément. et obtenir de réponse de seulement quelques demandes. et même sans exception, ont été jetés.J'ai été à essayer de comprendre ce pendant des jours (littéralement). Vous venez m'ont aidé à améliorer ma performance de 83%, et j'ai appris quelque chose de nouveau avec les requêtes HTTP et les threads. J'ai mon
DefaultConnectionLimit
définie sur le port du nombre de thread retourné à partir deThreadPool.GetAvailableThreads()
de sorte que je n'aurais pas trop de connexions. Merci!OriginalL'auteur Shiv Kumar
Il dépend de la façon dont vous le faites. Et si vous avez des réponses déclenchées à partir d'un thread à un autre, vous le faites mal.
Peut-être une bonne façon de le faire serait de concevoir une unité de travail qui accepte votre URL et de publier de l'information en tant que paramètres. Il sera alors le feu jusqu'à une nouvelle HttpWebRequest exemple, la poignée de la réponse et de transmettre cette réponse (avec les adaptations nécessaires/nettoyage).
Ces unités de travail pourrait alors être démarré dans des threads, avec les réponses recueillies. Une fois que tous les threads sont terminées, vous pouvez alors traiter les résultats.
OriginalL'auteur rvxnet