2012-09-05 24 views
6

tengo este códigode ejecución asíncrono HttpWebRequest llamadas

using (var stream = new StreamWriter(request.GetRequestStream(), Encoding)) 
    stream.Write(body.ToString()); 

que necesito para que sea asíncrono. Por lo que yo entiendo, esto significa que necesito cambiar la llamada al request.GetRequestStream() al asychronous.BeginGetRequestStream(). He visto el ejemplo this pero no puedo encontrar la forma de aplicarlo a este escenario. ¿Alguien puede ayudar?

+0

¿Qué versión de .NET estás usando? Es trivial con .NET 4.5. –

+0

Es 4. No puedo usar 4.5 todavía. –

+0

Todavía es posible en 4 ¿verdad? –

Respuesta

12

La documentación tiene un buen ejemplo (http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetrequeststream(v=vs.100).aspx):

using System; 
using System.Net; 
using System.IO; 
using System.Text; 
using System.Threading; 

class HttpWebRequestBeginGetRequest 
{ 
    private static ManualResetEvent allDone = new ManualResetEvent(false); 
public static void Main(string[] args) 
{ 
    // Create a new HttpWebRequest object. 
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.contoso.com/example.aspx"); 

    request.ContentType = "application/x-www-form-urlencoded"; 

    // Set the Method property to 'POST' to post data to the URI. 
    request.Method = "POST"; 

    // start the asynchronous operation 
    request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request); 

    // Keep the main thread from continuing while the asynchronous 
    // operation completes. A real world application 
    // could do something useful such as updating its user interface. 
    allDone.WaitOne(); 
} 

private static void GetRequestStreamCallback(IAsyncResult asynchronousResult) 
{ 
    HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState; 

    // End the operation 
    Stream postStream = request.EndGetRequestStream(asynchronousResult); 

    Console.WriteLine("Please enter the input data to be posted:"); 
    string postData = Console.ReadLine(); 

    // Convert the string into a byte array. 
    byte[] byteArray = Encoding.UTF8.GetBytes(postData); 

    // Write to the request stream. 
    postStream.Write(byteArray, 0, postData.Length); 
    postStream.Close(); 

    // Start the asynchronous operation to get the response 
    request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request); 
} 

private static void GetResponseCallback(IAsyncResult asynchronousResult) 
{ 
    HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState; 

    // End the operation 
    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult); 
    Stream streamResponse = response.GetResponseStream(); 
    StreamReader streamRead = new StreamReader(streamResponse); 
    string responseString = streamRead.ReadToEnd(); 
    Console.WriteLine(responseString); 
    // Close the stream object 
    streamResponse.Close(); 
    streamRead.Close(); 

    // Release the HttpWebResponse 
    response.Close(); 
    allDone.Set(); 
} 
+0

¿Cómo modifico este código para devolver algo (por ejemplo, la cadena de respuesta) de GetResponseCallBack a la persona que llama original, ya que AsyncCallBack requiere que la firma tenga un tipo de devolución anómala? –

+0

no tenía ni idea de cómo hacer esto, y esta respuesta es más clara para mí, ¡gracias! –

0

se puede entender por este código.

El programa define dos clases para uso propio, la clase RequestState, que pasa datos a través de llamadas asincrónicas, y la clase ClientGetAsync, que implementa la solicitud asincrónica a un recurso de Internet.

La clase RequestState conserva el estado de la solicitud en llamadas a los métodos asincrónicos que dan servicio a la solicitud. Contiene instancias de WebRequest y Stream que contienen la solicitud actual al recurso y la secuencia recibida en respuesta, un búfer que contiene los datos actualmente recibidos del recurso de Internet y un StringBuilder que contiene la respuesta completa. Un RequestState se pasa como el parámetro de estado cuando el método AsyncCallback se registra con WebRequest.BeginGetResponse.

La clase ClientGetAsync implementa una solicitud asincrónica a un recurso de Internet y escribe la respuesta resultante a la consola. Contiene los métodos y propiedades que se describen en la siguiente lista.

La propiedad allDone contiene una instancia de la clase ManualResetEvent que señala la finalización de la solicitud.

El método Main() lee la línea de comando y comienza la solicitud del recurso de Internet especificado. Crea el wreq de WebRequest y RequestState rs, llama a BeginGetResponse para comenzar a procesar la solicitud y luego llama al método allDone.WaitOne() para que la aplicación no salga hasta que se complete la devolución de llamada. Después de leer la respuesta del recurso de Internet, Main() lo escribe en la consola y la aplicación finaliza.

El método showusage() escribe una línea de comando de ejemplo en la consola. Es llamado por Main() cuando no se proporciona URI en la línea de comando.

El método RespCallBack() implementa el método de devolución de llamada asincrónica para la solicitud de Internet. Crea la instancia WebResponse que contiene la respuesta del recurso de Internet, obtiene la secuencia de respuesta y luego comienza a leer los datos de la secuencia de forma asincrónica.

El método ReadCallBack() implementa el método de devolución de llamada asincrónica para leer el flujo de respuesta. Transfiere los datos recibidos del recurso de Internet a la propiedad ResponseData de la instancia RequestState, luego inicia otra lectura asincrónica de la secuencia de respuesta hasta que no se devuelven más datos. Una vez que se han leído todos los datos, ReadCallBack() cierra la secuencia de respuesta y llama al método allDone.Set() para indicar que toda la respuesta está presente en ResponseData.

using System; 
using System.Net; 
using System.Threading; 
using System.Text; 
using System.IO; 

// The RequestState class passes data across async calls. 
public class RequestState 
{ 
    const int BufferSize = 1024; 
    public StringBuilder RequestData; 
    public byte[] BufferRead; 
    public WebRequest Request; 
    public Stream ResponseStream; 
    // Create Decoder for appropriate enconding type. 
    public Decoder StreamDecode = Encoding.UTF8.GetDecoder(); 

    public RequestState() 
    { 
     BufferRead = new byte[BufferSize]; 
     RequestData = new StringBuilder(String.Empty); 
     Request = null; 
     ResponseStream = null; 
    }  
} 

// ClientGetAsync issues the async request. 
class ClientGetAsync 
{ 
    public static ManualResetEvent allDone = new ManualResetEvent(false); 
    const int BUFFER_SIZE = 1024; 

    public static void Main(string[] args) 
    { 
     if (args.Length < 1) 
     { 
     showusage(); 
     return; 
     } 

     // Get the URI from the command line. 
     Uri httpSite = new Uri(args[0]); 

     // Create the request object. 
     WebRequest wreq = WebRequest.Create(httpSite); 

     // Create the state object. 
     RequestState rs = new RequestState(); 

     // Put the request into the state object so it can be passed around. 
     rs.Request = wreq; 

     // Issue the async request. 
     IAsyncResult r = (IAsyncResult) wreq.BeginGetResponse(
     new AsyncCallback(RespCallback), rs); 

     // Wait until the ManualResetEvent is set so that the application 
     // does not exit until after the callback is called. 
     allDone.WaitOne(); 

     Console.WriteLine(rs.RequestData.ToString()); 
    } 

    public static void showusage() { 
     Console.WriteLine("Attempts to GET a URL"); 
     Console.WriteLine("\r\nUsage:"); 
     Console.WriteLine(" ClientGetAsync URL"); 
     Console.WriteLine(" Example:"); 
     Console.WriteLine("  ClientGetAsync http://www.contoso.com/"); 
    } 

    private static void RespCallback(IAsyncResult ar) 
    { 
     // Get the RequestState object from the async result. 
     RequestState rs = (RequestState) ar.AsyncState; 

     // Get the WebRequest from RequestState. 
     WebRequest req = rs.Request; 

     // Call EndGetResponse, which produces the WebResponse object 
     // that came from the request issued above. 
     WebResponse resp = req.EndGetResponse(ar);   

     // Start reading data from the response stream. 
     Stream ResponseStream = resp.GetResponseStream(); 

     // Store the response stream in RequestState to read 
     // the stream asynchronously. 
     rs.ResponseStream = ResponseStream; 

     // Pass rs.BufferRead to BeginRead. Read data into rs.BufferRead 
     IAsyncResult iarRead = ResponseStream.BeginRead(rs.BufferRead, 0, 
     BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs); 
    } 


    private static void ReadCallBack(IAsyncResult asyncResult) 
    { 
     // Get the RequestState object from AsyncResult. 
     RequestState rs = (RequestState)asyncResult.AsyncState; 

     // Retrieve the ResponseStream that was set in RespCallback. 
     Stream responseStream = rs.ResponseStream; 

     // Read rs.BufferRead to verify that it contains data. 
     int read = responseStream.EndRead(asyncResult); 
     if (read > 0) 
     { 
     // Prepare a Char array buffer for converting to Unicode. 
     Char[] charBuffer = new Char[BUFFER_SIZE]; 

     // Convert byte stream to Char array and then to String. 
     // len contains the number of characters converted to Unicode. 
     int len = 
     rs.StreamDecode.GetChars(rs.BufferRead, 0, read, charBuffer, 0); 

     String str = new String(charBuffer, 0, len); 

     // Append the recently read data to the RequestData stringbuilder 
     // object contained in RequestState. 
     rs.RequestData.Append(
      Encoding.ASCII.GetString(rs.BufferRead, 0, read));   

     // Continue reading data until 
     // responseStream.EndRead returns –1. 
     IAsyncResult ar = responseStream.BeginRead( 
      rs.BufferRead, 0, BUFFER_SIZE, 
      new AsyncCallback(ReadCallBack), rs); 
     } 
     else 
     { 
     if(rs.RequestData.Length>0) 
     { 
      // Display data to the console. 
      string strContent;     
      strContent = rs.RequestData.ToString(); 
     } 
     // Close down the response stream. 
     responseStream.Close();   
     // Set the ManualResetEvent so the main thread can exit. 
     allDone.Set();       
     } 
     return; 
    }  
} 
Cuestiones relacionadas