2009-12-10 15 views
6

La siguiente función se tire hacia abajo primeras X mensajes de Twitter manguera de bomberos, pero parece que bloquea WebResponse y nunca sale de la función:¿Por qué WebResponse nunca termina al leer twitter firehose stream?

public void GetStatusesFromStream(string username, string password, int nMessageCount) 
{ 
    WebRequest request = WebRequest.Create("http://stream.twitter.com/1/statuses/sample.json"); 
    request.Credentials = new NetworkCredential(username, password); 

    using (WebResponse response = request.GetResponse()) 
    { 
     using (var stream = response.GetResponseStream()) 
     { 
      using (var reader = new StreamReader(stream)) 
      { 
       while (!reader.EndOfStream) 
       { 
        Console.WriteLine(reader.ReadLine()); 

        if (nMessageCount-- < 0) 
         break; 
       } 
       Console.WriteLine("Start iDispose"); 
      } 
      Console.WriteLine("Never gets here!!!"); 
     } 
    } 

    Console.WriteLine("Done - press a key to exit"); 
    Console.ReadLine(); 
} 

Pero el siguiente funciona bien:

public void GetStatusesFromStreamOK(string username, string password, int nMessageCount) 
    { 
    byte[] encbuff = System.Text.Encoding.UTF8.GetBytes(username + ":" + password); 
    //request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(encbuff)); 

    string requestString = "GET /1/statuses/sample.json HTTP/1.1\r\n"; 
    requestString += "Authorization: " + "Basic " + Convert.ToBase64String(encbuff) + "\r\n"; 
    requestString += "Host: stream.twitter.com\r\n"; 
    requestString += "Connection: keep-alive\r\n"; 
    requestString += "\r\n"; 

    using (TcpClient client = new TcpClient()) 
    { 
     client.Connect("stream.twitter.com", 80); 

     using (NetworkStream stream = client.GetStream()) 
     { 
      // Send the request. 
      StreamWriter writer = new StreamWriter(stream); 
      writer.Write(requestString); 
      writer.Flush(); 

      // Process the response. 
      StreamReader rdr = new StreamReader(stream); 

      while (!rdr.EndOfStream) 
      { 
       Console.WriteLine(rdr.ReadLine()); 
       if (nMessageCount-- < 0) 
        break; 
      } 

     } 
    } 

    Console.WriteLine("Done - press a key to exit"); 
    Console.ReadLine(); 

} 

¿Qué estoy haciendo ¿incorrecto?

+0

¿Sabes dónde está colgado? ¿Puede adjuntar un depurador y obtener un seguimiento de la pila? Offhand, no hay nada de malo en tu código. Es posible que el servidor se comporte mal o que haya un error en StreamReader. Puede usar las técnicas en http://ferozedaud.blogspot.com/2009/08/tracing-with-systemnet.html para descubrir qué sucede bajo las cubiertas. Eso sería un buen punto de partida. – feroze

+0

Si elimino las instrucciones de uso y reemplazo con reader.close() veo el mismo problema, y ​​el monitor de red muestra que la aplicación aún está recibiendo datos pero no regresa desde reader.close(). PS: solo el comportamiento probado en Vista. – martimedia

+0

No puedo reproducirlo (VS 2008 en Windows 7 64 bit). Está funcionando totalmente bien ... –

Respuesta

3

de emitir su WebRequest como un HttpWebRequest, luego antes de la llamada de interrupción request.Abort()

+0

Gracias, añadiendo request.Abort() hizo el truco, independientemente de lanzar WebRequest como HttpWebRequest. No estoy seguro de por qué el código original funcionó para algunos, pero recomendaría encarecidamente a las personas que agreguen una solicitud. Acceda a su código si quieren ejecutar en una amplia gama de clientes .NET. – martimedia

+0

Pasé 12 horas tirando de mi cabello sobre esto:^( –

-1

parece que tiene algo que ver con el proceso de eliminación o el "uso" ...

El siguiente código funciona bien (sin el "uso" declaraciones):

public static void GetStatusesFromStream(string username, string password, int nMessageCount) 
    { 
     WebRequest request = WebRequest.Create("http://stream.twitter.com/1/statuses/sample.json"); 
     request.Credentials = new NetworkCredential(username, password); 

     WebResponse response = request.GetResponse(); 
     { 
      var stream = response.GetResponseStream(); 
      { 
       var reader = new StreamReader(stream); 
       { 
        while (!reader.EndOfStream) 
        { 
         Console.WriteLine(reader.ReadLine()); 

         if (nMessageCount-- < 0) 
          break; 
        } 
       } 
       Console.WriteLine("Never gets here!!!"); 
      } 
     } 

     Console.WriteLine("Done - press a key to exit"); 
     Console.ReadLine(); 
    } 
+0

Estoy de acuerdo en que va más allá, pero solo porque está demorando la recolección de basura de .NET. Si ejecuta la función un par de veces, se activará la recolección de elementos no utilizados y el programa se bloqueará como antes. – martimedia

Cuestiones relacionadas