2009-08-01 52 views
25

Büyük bir sorunum var: Bir kerede 200 nesne göndermem ve zaman aşımlarından kaçınmam gerekiyor.System.Net.WebException: İşlem zaman aşımına uğradı

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; 
     } 
    }  
} 

Bu hatayı üretir:

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

requestCount döngü benim taban kodunda dışında çalışıyor ama benim projeye ekleyin zaman bu hatayı alıyorum. request.Timeout = 200;'u ayarlamayı denedim, ancak yardımcı olmadı.

+1

. Kodunuz derlenmeyecek: 'WebRequest 'kurucusu' korumalı '. "..." yerine "// ..." ifadesini kullandıysanız da kullanışlı olurdu. –

cevap

0

WCF'yi kullanırken geçirdiğim veri miktarı nedeniyle aynı sorunu yaşadım. Her yerde zaman aşımlarını değiştirdiğimi hatırlıyorum ama sorun devam ediyordu. Sonunda yaptığım şey, bağlantıyı akış isteği olarak açmaktı, müşteriyi ve sunucu tarafını değiştirmem gerekiyordu, ama bu şekilde çalışıyor. Bir akış bağlantısı olduğundan, sunucu akış sona erene kadar okumaya devam etti.

32

Anlamı ne anlama geliyor? Operasyonun tamamlanması çok uzun sürdü.

BTW, WebRequest.Timeout bakmak ve size 1/5 saniye için zaman aşımı kurdum göreceksiniz.

24

Sana WebClient.UploadValues ​​kullanan ilk kod örneğinde hakkında emin değilim, sizin çevreleyen kod daha yapıştırın olabilir, gerçekten yeterli gitmek değil mi? senin WebRequest kodu ile ilgili olarak, burada oynayan iki şey vardır:

  1. Yalnızca ** açmakta ve okuyarak tepki gövdesini hiç okumamış yanıtın başlıklarını istekte (sonuna kadar) ResponseStream. Bu nedenle, WebRequest istemcisi, bağlantıyı her an açık bir şekilde talep etmenizi sağlayacak şekilde bağlantıyı açık bir şekilde bırakır. Yanıt gövdesini tamamlanana kadar okuyun (akış sizin için otomatik olarak kapanır), akışı temizleyin ve kapatın (veya WebRequest örneği) veya GC'nin işini yapmasını bekleyin, bağlantınız açık kalacaktır.

  2. Bu kadar müşteri tamamlamak için bir şans verilmez bunların elden asla sonra ilk iki bağlantılarını kullanıp demektir 2'nin aynı ana bilgisayara aktif bağlantılarının varsayılan bir maksimum miktarda bir sonraki istek zaman aşımına ulaşmadan önce (milisaniye, btw, bu yüzden 0,2 saniyeye ayarladınız - varsayılan değer iyi olmalıdır).

Eğer yanıtın vücudu istemiyoruz (veya sadece yüklenen ya da bir şey POSTed ve bir yanıt beklemek değildir ettik), sadece kapanacak olan dere veya müşteri kapatırsanız sizin için akış.

Bunu düzeltmek için en kolay yolu, tek kullanımlık nesneler üzerinde bloklarını kullanarak kullanmak emin olmaktır:

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 
} 

Başka bir çözüm aynı ana bilgisayara 200 eşzamanlı bağlantı sağlamaktır. Ancak, çoklu iş parçacığı için bu işlemi planlıyoruz sürece birden, eşzamanlı bağlantı gerekiyordu bu yüzden, bu gerçekten size yardımcı olmayacaktır:

ServicePointManager.DefaultConnectionLimit = 200; 

Eğer kodundaki en iyi şey zaman aşımları alıyoruz zaman yapmak için bu zaman aşımını kodunuzun dışında yeniden oluşturmaya çalışın. Eğer yapamazsan, problem muhtemelen senin kodunda yatıyor.Bunun için genellikle cURL kullanıyorum ya da basit bir GET isteği ise sadece bir web tarayıcısı.

** Gerçekte, aslında HTTP başlıklarını ve ayrıca vücudun başlangıcını içeren yanıttaki ilk veri yığınını talep ediyorsunuz. Bu yüzden çıktı akışından okumadan önce HTTP başlık bilgisini (İçerik Kodlama, Set-Çerez vb.) Okumak mümkündür. Akışı okuduğunuzda, sunucudan daha fazla veri alınır. WebRequest'in sunucuya olan bağlantısı, bu akışın sonuna ulaşana kadar (etkin bir şekilde kapatılamayacak şekilde) kapanana kadar açık tutulur, kendiniz el ile kapatarak veya atılır. There's more about this here.

+0

@Matthew: "HEAD" göndermekten emin misiniz? Bunun olduğunu hiç görmedim. –

+0

Özür dileriz, HEAD (HEAD'lar sadece * başlıklarını talep ettiğiniz yerde) demek istemiyorum, yani ilk yanıt sadece üstbilgileri (yani, sadece bir HEAD isteği gönderirseniz elde edeceğiniz şey) içerir. Hatamı düzeltmek için düzenledim. –

+0

@Matthew: Yine, cevabın yalnızca başlık içerdiğini düşünürsünüz? İstemci ve sunucu arasında GetRequestStream'in çağrıldığı sırada başka bir paket değiş tokuşu var mı? –

32

WebResponse nesnesini kapatın/atın. Kod yazarken, gerçek kodu göndermeye çalışın BTW,

+3

İyi yakalama, ama ona nasıl olduğunu göstermelisin, yoksa yapacağım. –

+4

Kapatma/imha etme konusunda yardımcı olmuyor –

+0

Teşekkür ederiz! İşe yaradı! –

İlgili konular