2010-09-26 11 views
6

Witam Mam funkcję, która przekazuje adres URL Pobierz parametry do pliku php na serwerze internetowym i czeka na odpowiedź z pliku (zwykle zajmuje to 10-20 sekund). Chcę umieścić to w pętli, ponieważ muszę wysłać te żądania Get do około 5 różnych plików php na raz, ale kiedy próbuję dodać to do pętli funkcja sprawi, że pętla będzie czekać aż plik zwróci odpowiedź zanim pójdzie Przechodząc do następnego.Asynchroniczne WebRequests za pomocą C#

public string HttpGet(string URI, string Parameters) 
    { 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URI + Parameters); 

     HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
     StreamReader resStream = new StreamReader(response.GetResponseStream()); 
      return resStream.ReadToEnd().Trim(); 
    } 

    private void SendCommand() 
    { 
     for(int i = 0; i <= 4; i++) 
     { 
      AddRTB(HttpGet(url, paramater)); 
     } 
    } 

Czy istnieje sposób na wysłanie wszystkich 5 żądań na raz bez oczekiwania na zakończenie poprzedniego? (Myślałem o przewijaniu go, ale niestety nigdy go nie dotknąłem, nie wiem od czego zacząć).

+1

Threading jest droga Aby to osiągnąć, musisz poczekać, aż wszystkie 5 odpowiedzą, zanim przejdziesz dalej. – ChrisF

Odpowiedz

9

Zamiast używać metody GetResponse() można użyć BeginGetResponse(), która nie jest blokadą. Otrzymuje wywołanie zwrotne, które może następnie obsłużyć obiekt WebResponse po jego powrocie. Przykład w łączu daje dobry pomysł, jak sprawić, aby wątek główny czekał na wszystkie odpowiedzi do powrotu.

0

Użyj metody WebClient za pomocą metod asynchronicznych.

Rozpoczęcie \ Koniec jest trudniejsze w użyciu.

9

Oto dwa podejścia wykorzystujące licencję OC.

Pierwsze czeka na wszystkie żądania, aby zakończyć, zanim dostęp do wszystkich wyników

var runningTasks = new List<Task<string>>(); 

for (int ii = 0; ii <= 4; ii++) 
{ 
    var wreq = (HttpWebRequest)WebRequest.Create("..." + ii); 

    var taskResp = Task.Factory.FromAsync<WebResponse>(wreq.BeginGetResponse, 
                wreq.EndGetResponse, 
                null); 
    var taskResult = taskResp.ContinueWith(tsk => new StreamReader(tsk.Result.GetResponseStream()).ReadToEnd().Trim()); 
    runningTasks.Add(taskResult); 
} 

Task.WaitAll(runningTasks.ToArray()); 
IEnumerable<string> results = runningTasks.Select(tsk => tsk.Result); 

a drugi robi coś z każdego wyniku, jak to jest w:

for (int ii = 0; ii <= 4; ii++) 
{ 
    var wreq = (HttpWebRequest)WebRequest.Create("..." + ii); 

    var taskResp = Task.Factory.FromAsync<WebResponse>(wreq.BeginGetResponse, 
                wreq.EndGetResponse, 
                null); 
    taskResp.ContinueWith(tsk => new StreamReader(tsk.Result.GetResponseStream()).ReadToEnd().Trim()) 
      .ContinueWith((Task<string> trs) => 
       { 
        var result = trs.Result; 
        DoSomthingWithTheResult(result); 
       }); 
} 
+0

+1. Nawet jeśli odpowiedź @ linuxuser27 nie ma nic złego, to ta odpowiedź lepiej odpowiada na pytanie i będzie znacznie łatwiejsza do wdrożenia –

+0

+1 Rzeczywiście tak jest. Metoda "ContinueWith()" jest dobry pomysł: – linuxuser27

+0

A jak by to się zmieniło, gdybym potrzebował wysłać trochę danych za pomocą żądania HTTP POST z BeginGetRequestStream/EndGetRequestSteam? http://stackoverflow.com/questions/4190903 –

Powiązane problemy