2012-09-05 12 views
6

ich diesen Code haben asynchroneImplementierung von HttpWebRequest Async nennt

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

Ich muss es machen. Soweit ich es verstehe, bedeutet dies, dass ich den Anruf zu request.GetRequestStream() zu asychronous.BeginGetRequestStream() ändern muss. Ich habe this Beispiel gesehen aber kann nicht herausfinden, wie man das auf dieses Szenario anwendet. Kann jemand helfen?

+0

Welche Version von .NET verwenden Sie? Es ist trivial mit .NET 4.5. –

+0

Es ist 4. Ich kann 4.5 noch nicht verwenden. –

+0

Es ist noch in 4 rechts möglich? –

Antwort

12

Die Dokumentation hat ein gutes Beispiel (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

Wie ändere ich diesen Code, um etwas (z. B. die Antwortzeichenfolge) von GetResponseCallBack an den ursprünglichen Aufrufer zurückzugeben, da das AsyncCallBack die Signatur benötigt, um einen ungültigen Rückgabetyp zu haben? –

+0

Ich hatte keine Ahnung, wie man das macht, und diese Antwort klarer es für mich komplett danke! –

0

Sie von diesem Code verstehen können.

Das Programm definiert zwei Klassen für seine eigene Verwendung, die RequestState-Klasse, die Daten über asynchrone Aufrufe weitergibt, und die ClientGetAsync-Klasse, die die asynchrone Anforderung an eine Internetressource implementiert.

Die RequestState-Klasse behält den Status der Anforderung über Aufrufe an die asynchronen Methoden bei, die die Anforderung bedienen. Er enthält WebRequest- und Stream-Instanzen, die die aktuelle Anforderung an die Ressource und den als Antwort empfangenen Stream enthalten, einen Puffer, der die aktuell von der Internet-Ressource empfangenen Daten enthält, und einen StringBuilder, der die vollständige Antwort enthält. Wenn die AsyncCallback-Methode mit WebRequest.BeginGetResponse registriert ist, wird ein Anforderungsstatus als Statusparameter übergeben.

Die ClientGetAsync-Klasse implementiert eine asynchrone Anforderung an eine Internetressource und schreibt die resultierende Antwort in die Konsole. Es enthält die in der folgenden Liste beschriebenen Methoden und Eigenschaften.

Die allDone-Eigenschaft enthält eine Instanz der ManualResetEvent-Klasse, die den Abschluss der Anforderung signalisiert.

Die Main() -Methode liest die Befehlszeile und beginnt die Anforderung für die angegebene Internetressource. Er erstellt WebRequest wreq und RequestState rs, ruft BeginGetResponse auf, um mit der Verarbeitung der Anforderung zu beginnen, und ruft dann die allDone.WaitOne() -Methode auf, damit die Anwendung erst beendet wird, wenn der Rückruf abgeschlossen ist. Nachdem die Antwort von der Internet-Ressource gelesen wurde, schreibt Main() sie in die Konsole und die Anwendung wird beendet.

Die Methode showusage() schreibt eine Beispielbefehlszeile auf der Konsole. Es wird von Main() aufgerufen, wenn in der Befehlszeile kein URI bereitgestellt wird.

Die RespCallBack() - Methode implementiert die asynchrone Rückrufmethode für die Internetanforderung. Es erstellt die WebResponse-Instanz, die die Antwort von der Internet-Ressource enthält, ruft den Antwortstream ab und beginnt dann mit dem asynchronen Lesen der Daten aus dem Stream.

Die ReadCallBack() - Methode implementiert die asynchrone Rückrufmethode zum Lesen des Antwortdatenstroms. Er überträgt Daten, die von der Internet-Ressource empfangen werden, in die ResponseData-Eigenschaft der RequestState-Instanz und startet dann einen weiteren asynchronen Lesevorgang des Antwortdatenstroms, bis keine Daten mehr zurückgegeben werden. Nachdem alle Daten gelesen wurden, schließt ReadCallBack() den Antwortdatenstrom und ruft die allDone.Set() -Methode auf, um anzuzeigen, dass die gesamte Antwort in ResponseData vorhanden ist.

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