2010-09-26 9 views
6

Ciao ho una funzione che passa url Ottieni parametri su un file php su un server web e aspetta una risposta dal file (normalmente richiede 10-20 secondi). Voglio mettere questo in un ciclo perché devo inviare queste richieste Get a circa 5 diversi file php in una sola volta ma quando provo ad aggiungerlo a un ciclo la funzione fa in modo che il ciclo attenda fino a quando il file non restituisce la risposta prima che vada al prossimo.WebRequest asincroni con 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)); 
     } 
    } 

C'è un modo per inviare tutte e 5 le richieste contemporaneamente senza aspettare che il precedente termini? (stavo pensando di inserirlo ma purtroppo non l'ho mai toccato prima non so da dove cominciare.)

+1

Threading è il modo per fare questo, anche se dovrai aspettare che tutti e 5 rispondano prima di continuare. – ChrisF

risposta

9

Invece di utilizzare il metodo GetResponse(), è possibile utilizzare lo BeginGetResponse() che è una chiamata non bloccante. Richiede una richiamata che può quindi gestire l'oggetto WebResponse quando alla fine ritorna. L'esempio nel collegamento ti darà una buona idea di come il thread principale attenda il ritorno di tutte le risposte.

0

Utilizzare il metodo WebClient con Async.

Begin \ End è più difficile da utilizzare.

9

Ecco due approcci che utilizzano il TPL.

Le prime attese per tutte le richieste per completare prima di accedere a qualsiasi dei risultati

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

e la seconda fa qualcosa con ogni risultato come viene in:

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 Anche se la risposta @ linuxuser27 non ha nulla di sbagliato, questo risponde meglio alla domanda e sarà molto più facile da implementare –

+0

+1 Il metodo 'ContinueWith()' è un buona idea – linuxuser27

+0

E come cambierebbe se ho bisogno di inviare alcuni dati con richiesta POST HTTP con BeginGetRequestStream/EndGetRequestSteam? http://stackoverflow.com/questions/4190903 –