2010-09-26 31 views
6

Hola tengo una función que pasa url Obtener parámetros a un archivo php en un servidor web y espera una respuesta del archivo (normalmente toma 10-20 segundos). Quiero poner esto dentro de un bucle porque tengo que enviar estas solicitudes Get a aproximadamente 5 archivos php diferentes a la vez, pero cuando intento agregarlo a un bucle, la función hace que el bucle espere hasta que el archivo devuelva la respuesta antes de que vaya. en el siguiente.WebRequests asíncronas usando 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)); 
     } 
    } 

¿Hay alguna manera de que pueda enviar las 5 solicitudes a la vez sin esperar a que el anterior termine? (Estaba pensando en enhebrarlo pero, por desgracia, nunca lo toqué antes, no sé por dónde empezar)

+1

Threading es el camino para ir por esto, aunque tendrás que esperar que los 5 respondan antes de continuar. – ChrisF

Respuesta

9

En lugar de usar el método GetResponse(), puede usar BeginGetResponse() que es una llamada sin bloqueo. Toma una devolución de llamada que luego puede manejar el objeto WebResponse cuando finalmente regresa. El ejemplo en el enlace le dará una buena idea de cómo hacer que el hilo principal espere a que vuelvan todas las respuestas.

9

Aquí hay dos enfoques que utilizan el TPL.

Las primeras espera a que todas las solicitudes para completar antes de acceder a cualquiera de los resultados

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

y el segundo lo hace algo con cada resultado, ya que viene en:

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. Incluso si @ linuxuser27 respuesta no tiene nada de malo, este responde mejor a la pregunta y será mucho más fácil de implementar. –

+0

+1 De hecho lo es. El método 'ContinueWith()' es buena idea. – linuxuser27

+0

¿Y cómo cambiaría esto si tuviera que enviar algunos datos con la solicitud HTTP POST con BeginGetRequestStream/EndGetRequestSteam? http://stackoverflow.com/questions/4190903 –

Cuestiones relacionadas