2009-08-01 6 views
25

Ich habe ein großes Problem: Ich muss 200 Objekte auf einmal senden und Timeouts vermeiden.System.Net.WebException: Die Operation hat abgelaufen

while (true) 
{ 

    NameValueCollection data = new NameValueCollection(); 
    data.Add("mode", nat); 

    using (var client = new WebClient()) 
    { 
     byte[] response = client.UploadValues(serverA, data); 
     responseData = Encoding.ASCII.GetString(response); 

     string[] split = Javab.Split(new[] { '!' }, StringSplitOptions.RemoveEmptyEntries); 
     string command = split[0]; 
     string server = split[1]; 
     string requestCountStr = split[2]; 

     switch (command) 
     { 
      case "check": 
       int requestCount = Convert.ToInt32(requestCountStr); 

       for (int i = 0; i < requestCount; i++) 
       { 
        Uri myUri = new Uri(server); 
        WebRequest request = WebRequest.Create(myUri); 
        request.Timeout = 200000; 
        WebResponse myWebResponse = request.GetResponse(); 
       } 
       break; 
     } 
    }  
} 

Dies erzeugt den Fehler:

Unhandled Exception: System.Net.WebException: The operation has timed out 
at System.Net.HttpWebRequest.GetResponse() 
at vir_fu.Program.Main(String[] args) 

Die requestCount Schleife arbeitet außerhalb meines Basiscode in Ordnung, aber wenn ich es mein Projekt hinzufügen bekomme ich diesen Fehler. Ich habe versucht, request.Timeout = 200; Einstellung, aber es hat nicht geholfen.

+1

BTW, wenn Sie Code schreiben, versuchen Sie, echten Code zu posten. Dein Code würde nicht kompilieren: Der 'WebRequest' Konstruktor ist 'protected'. Es wäre auch praktisch, wenn Sie anstelle von "..." "// ..." verwenden würden. –

Antwort

0

Ich erinnere mich, ich hatte das gleiche Problem eine Weile zurück mit WCF aufgrund der Menge der Daten, die ich übergeben wurde. Ich erinnere mich, dass ich die Timeouts überall änderte, aber das Problem blieb bestehen. Was ich schließlich tat, war, die Verbindung als Stromanforderung zu öffnen, ich musste die Klienten- und die Serverseite ändern, aber es funktioniert so. Da es sich um eine Streamverbindung handelte, las der Server weiter, bis der Stream beendet wurde.

32

Es bedeutet, was es sagt. Die Operation dauerte zu lange.

BTW, Blick auf WebRequest.Timeout und Sie werden sehen, dass Sie Timeout für 1/5 Sekunde festgelegt haben.

24

Ich bin mir nicht sicher über Ihren ersten Code-Beispiel, wo Sie WebClient.UploadValues ​​verwenden, es ist nicht wirklich genug, um fortzufahren, könnten Sie mehr von Ihrem umgebenden Code einfügen? hier in Bezug auf Ihrem WebRequest-Code, gibt es zwei Dinge im Spiel:

  1. Sie sind nur die Header der Antwort anfordert **, die Sie nie den Körper der Antwort durch das Öffnen und Lesen (zu Ende) gelesen der Antwortstream. Aus diesem Grund lässt der WebRequest-Client die Verbindung hilfreich offen und erwartet, dass Sie den Body jederzeit anfordern. Solange Sie den Antworttext nicht vollständig gelesen haben (wodurch der Stream automatisch für Sie geschlossen wird), den Stream bereinigen und schließen (oder die WebRequest-Instanz) oder warten, bis der GC seine Aufgabe erledigt hat, bleibt Ihre Verbindung geöffnet.

  2. Sie haben eine Standard maximale Menge an aktiven Verbindungen zu dem gleichen Host von 2. Dies bedeutet, dass Sie Ihre ersten beiden Verbindungen verwenden und dann entsorgen nie von ihnen, damit Ihr Kunde die Möglichkeit nicht gegeben ist, die zu vervollständigen nächste Anfrage, bevor es sein Timeout erreicht (das ist Millisekunden, BTW, so dass Sie es auf 0,2 Sekunden eingestellt haben - die Standardeinstellung sollte in Ordnung sein).

Wenn Sie nicht wollen, um den Körper der Antwort (oder haben Sie gerade hochgeladen oder POSTed etwas und erwarten keine Antwort), einfach den Strom schließen, oder den Client, die das schließt Stream für dich.

Der einfachste Weg, dies zu beheben ist, dass Sie sicherstellen, dass Sie auf Einweg-Objekte verwenden mit:

for (int i = 0; i < ops1; i++) 
{ 
    Uri myUri = new Uri(site); 
    WebRequest myWebRequest = WebRequest.Create(myUri); 
    //myWebRequest.Timeout = 200; 
    using (WebResponse myWebResponse = myWebRequest.GetResponse()) 
    { 
     // Do what you want with myWebResponse.Headers. 
    } // Your response will be disposed of here 
} 

Eine andere Lösung ist 200 gleichzeitige Verbindungen zu dem gleichen Host zu ermöglichen. Allerdings, wenn Sie diesen Vorgang Multi-Thread-Planung sind so würden Sie mehrere, gleichzeitige Verbindungen benötigen, wird dies nicht wirklich helfen:

ServicePointManager.DefaultConnectionLimit = 200; 

Wenn Sie Timeouts innerhalb Code bekommen, das Beste, was Zu tun ist, versuchen, dieses Timeout außerhalb Ihres Codes neu zu erstellen. Wenn Sie nicht können, liegt das Problem wahrscheinlich in Ihrem Code.Normalerweise verwende ich dafür cURL oder einfach einen Webbrowser, wenn es sich um eine einfache GET-Anfrage handelt.

** In Wirklichkeit fordern Sie tatsächlich den ersten Datenblock aus der Antwort an, der die HTTP-Header und auch den Anfang des Rumpfs enthält. Daher ist es möglich, HTTP-Header-Informationen (wie Content-Encoding, Set-Cookie usw.) vor dem Lesen aus dem Ausgabestream zu lesen. Während Sie den Stream lesen, werden weitere Daten vom Server abgerufen. Die Verbindung von WebRequest mit dem Server bleibt offen, bis Sie das Ende dieses Streams erreicht haben (effektiv schließen, da es nicht suchbar ist), manuell schließen Sie es selbst oder es wird entsorgt. There's more about this here.

+0

@Matthew: Bist du sicher, HEAD zu senden? Ich glaube nicht, dass ich das je gesehen habe. –

+0

Entschuldigung, ich meine nicht HEAD (HEAD's, wo Sie * nur * die Header anfragen), ich meine die erste Antwort enthält nur die Header (was Sie normalerweise bekommen würden, wenn Sie gerade eine HEAD Anfrage gesendet haben). Ich habe bearbeitet, um meinen Fehler zu beheben. –

+0

@Matthew: wieder, was Sie denken, die Antwort enthält nur Header? Schlagen Sie vor, dass zu dem Zeitpunkt, zu dem der 'GetRequestStream' aufgerufen wird, ein weiterer Paketaustausch zwischen dem Client und dem Server stattfindet? –

32

Schließen Sie Ihr WebResponse-Objekt/entsorgen Sie es.

+3

Guter Fang, aber Sie sollten ihm zeigen, wie, sonst werde ich. –

+4

Schließen/Entsorgen hilft nicht –

+0

Vielen Dank! Es funktionierte! –

Verwandte Themen