HttpWebRequest - kann ich mehrere Anrufe bei der sametime von mehreren threads
Benutze ich HttpWebRequest erstellen Anfragen für Webseiten, als zu analysieren Sie.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address);
dann, wenn mehrere threads rufen
HttpWebResponse response = (HttpWebResponse)request.GetResponse()
zur gleichen Zeit, sollte jeder seine eigene Antwort oder ist es möglich, für Faden 2, um die Antwort für thread7 zum Beispiel?
Obs: die Adresse ist die gleiche für alle threads, nur die POST-Parameter ändern
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;
}
}
dies ist, wie ich mit der Methode:
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);
}
Bitte sagen Sie mir, wo ich Fehler gemacht? Wie muss ich den code ändern? Bitte um Hilfe, ich kann nichts finden, was hilfreich auf dem web!
- Erstellen Sie die Anfrage im gleichen thread, ist das empfangen der Antwort? Wenn ja, dann sollten Sie nicht haben ein problem mit dem Antworten immer Durcheinander. Können Sie aktualisieren Sie Ihre Frage etwas konkreter sein? Danke!
- ja. GetPOSTWebsiteResponse Methode ist dabei sowohl httprequest und httpresponse. Yhis-Methode aufgerufen wird, die von jedem thread separatelly. Ich benutze keine anderen threads in irgendeiner Weise als diejenigen, die Sie sehen in dem Beispielcode. Hoffe, ich bin klarer, wenn nicht bitte Fragen
- Welche version von .Netz verwenden Sie?
- .Net framework 4
- Sie sollten mit den async-Methoden eher als Laich-threads. Dies ist vor allem eine I/O-bound-Vorgang laichen threads ist nicht wirklich notwendig. Zweitens, es sei denn, Sie geändert haben, die DefaultConnection begrenzen, Sie sind nicht immer mehr als 2 threads zur gleichen Zeit, da der default-limit 2 pro Domäne und da wirst du die gleiche domain...
- ja, aber mein code ist ein webservice in asp.net. Ich muss warten, bis die Anfrage empfangen wird. Wie kann ich das tun?
- Das ist der Sinn von async I/O ist es nicht? Ich poste etwas code
- Ich warte, wenn du kannst post-code! Vielen Dank für die Hilfe!
- Ich habe geschrieben/update einige code für Sie in einer Antwort weiter unten
Du musst angemeldet sein, um einen Kommentar abzugeben.
Um ehrlich zu sein, ich glaube nicht, dass die multi-threading, den Sie versuchen zu tun, ist zu bekommen Sie irgendwelche performance-Gewinne. Und zu sehen, dass es keine Schwelle für die Anzahl der threads, die Sie könnte die Schaffung hier das Potenzial für eine schlechtere Leistung als ein single-threaded (sequenziellen) Vorgang existiert.
Die ideale situation ist, dass Sie eine asynchrone Arbeitsabläufe. wo die Schleife ist so etwas wie dieses:
GetAsyncRequest
MakeAsyncRequest
ReceiveResponseAsync
ProcessResponse
WaitForAllRequestProcessingToComplete(Optional)
So, dass das Ergebnis jeder Schritt fließt in die nächste (falls es eine Folge) und die nächste. Und Sie sind der Verarbeitung der Antworten so bald, wie Sie Sie erhalten anstatt akkumulieren (Eintritt/blockieren) alle Antworten, bevor Sie Sie verarbeiten. Diese Art der Sache kann leicht getan werden mit Aufgaben und ContinueWith-in .NET 4.0 und sehen, dass Sie habe mit .NET 4.0, ich würde empfehlen Ihnen dringend, tun Sie es wie oben beschrieben.
Aber, wenn Sie nicht konvertieren Sie Ihre Bearbeitung in einem asynchronen workflow, dann...
Die Methode, die unten gezeigt wird, ist die Methode, die den Aufruf aus, um die Url und gibt eine Antwort zurück. Die Methode verwendet Asynchrone Aufrufe aber blockiert, da Ihr design zu sein scheint, als solche.
Würden Sie es so nennen:
Sehen, ob das funktioniert für Sie.
Wenn Sie wirklich brauchen, multi-Threading-Fähigkeit, natürlich zu sehen, dass Sie schlagen nur eine Seite hat, müsste man zur Messung der performance-Vorteile, da der Standort muss in der Lage sein zu handhaben, den Ansturm der Anfragen und der Kunde die Kosten der Erstellung von threads, nur für einige I/O-gebundene Aufgabe könnte am Ende wird zu teuer und am Ende keine performance-Gewinne.
Außerdem ohne Anpassung der DefaultConnectionLimit in der ServicePointManager, du wirst nie mehr als 2 threads entweder Möglichkeiten, da wirst du gegen eine domain und der Standardwert ist 2 threads pro domain.
Würd ich mich mit dem code, den ich hier vorgestellt habe und wenn es ein performance-problem nur dann würde ich schauen, tun es auf eine andere Weise.
Edit:
bei der Verwendung von Async-I/O-Sie sind nicht mit worker-threads, aber I/O-thread. Also im Grunde, die Sie nicht verwenden möchten QueueUserWorkItem (, threads zu erstellen), oder Sie sind nicht schaffen threads selbst.
Den code, den ich hier vorgestellt habe ist die Verwendung von Async-I/O-und wenn man auf ausführen mehrerer Anfragen simutaneously und so schnell wie möglich.
Die for-Schleife (in der zweiten code-listing) wird die Oberfläche fast sofort, obwohl in der Beispiel-loops für 100 Iterationen, und dann warten Sie, bis alle I/O-Anfragen zu beenden. Der ThreadPool-und OS-Griff-Ausführung des I/O-Aufträge, sobald und so schnell wie möglich. In der Tat, denn diese jobs sind I/O gebunden sind, werden Sie nicht sehen, Ihre CPU-Auslastung gehen, bis Sie entweder (es sei denn, man tut der cpu bestimmt die spätere Arbeit).
Nur spielen, mit der Dienste-Verwalter.DefaultConnectionLimit, um mehr Beschleunigung, wenn nötig. Beachten Sie, dass dies wirkt sich auf den service (der server) als auch, weil, wenn Sie machen eine Menge von gleichzeitigen Anfragen, die der server, die Sie aufrufen wird stark belastet und das kann nicht etwas sein, was Sie wollen. Es ist also eine balance, die Sie benötigen, zu streiken.
Nach dem Aufruf von Task.WaitAll, können Sie Durchlaufen Ihre Aufgaben Sammlung und erhalten Sie die Ergebnisse der einzelnen Aufgabe mit der syntax gezeigt, in die auskommentierte Zeile in der code-Auflistung.
ServicePointManager.DefaultConnectionLimit = noOfThread;
es hat mir wirklich geholfen, ich riefBeginGetResponse
aus mehreren Anfrage zur gleichen URL gleichzeitig. und erste Reaktion von nur einigen Anfragen. und auch keine exception geworfen wurden.DefaultConnectionLimit
auf den port eingestellt-thread-Anzahl zurück vonThreadPool.GetAvailableThreads()
so dass ich würde nicht zu viele verbindungen. Danke!Es hängt davon ab, wie Sie es tun. Und wenn Sie antwortet, ausgelöst von einem thread in einen anderen, dann machst du es falsch.
Vielleicht eine gute Möglichkeit dazu wäre die Entwicklung einer Einheit von arbeiten, die akzeptiert, dass Ihre URL und die post-Informationen als Parameter. Es wird dann Feuer eine neue HttpWebRequest-Instanz, Griff die Antwort und zurück übergeben, dass diese Antwort (mit allen notwendigen änderung/Bereinigung).
Diese Einheiten von Arbeit könnte Sie dann in getrennten threads mit den Antworten gesammelt werden. Wenn alle threads abgeschlossen sind, können Sie dann die Ergebnisse verarbeiten.