webentwicklung-frage-antwort-db.com.de

Abrufen der Antwort eines asynchronen HttpWebRequest

Ich frage mich, ob es eine einfache Möglichkeit gibt, die Antwort eines asynchronen httpwebrequest zu erhalten.

Ich habe diese Frage bereits gesehen here , aber alles, was ich zu tun versuche, ist, die Antwort (normalerweise json oder xml) in Form einer Zeichenfolge an eine andere Methode zurückzugeben, wo ich sie dann entsprechend analysieren kann.

Hier ist ein Code:

Ich habe diese zwei statischen Methoden hier, von denen ich denke, dass sie Thread-sicher sind, da alle Parameter übergeben werden und es keine gemeinsamen lokalen Variablen gibt, die von den Methoden verwendet werden.

public static void MakeAsyncRequest(string url, string contentType)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.ContentType = contentType;
    request.Method = WebRequestMethods.Http.Get;
    request.Timeout = 20000;
    request.Proxy = null;

    request.BeginGetResponse(new AsyncCallback(ReadCallback), request);
}

private static void ReadCallback(IAsyncResult asyncResult)
{
    HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
    try
    {
        using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult))
        {
            Stream responseStream = response.GetResponseStream();
            using (StreamReader sr = new StreamReader(responseStream))
            {
                //Need to return this response 
                string strContent = sr.ReadToEnd();
            }
       }
       manualResetEvent.Set();
    }
    catch (Exception ex)
    {
        throw ex;
   }
}
18
gdp

Angenommen, das Problem ist, dass Sie Schwierigkeiten haben, den zurückgegebenen Inhalt zu finden. Der einfachste Weg wäre wahrscheinlich async/await, wenn Sie ihn verwenden können. Noch besser wäre ein Wechsel zu HttpClient, wenn Sie .NET 4.5 verwenden, da es "nativ" asynchron ist.

Mit .NET 4 und C # 4 können Sie noch immer Task verwenden, um diese zu bündeln und den Zugriff auf das Endergebnis ein wenig zu erleichtern. Eine Option wäre zum Beispiel die unten stehende. Beachten Sie, dass die Main-Methode so lange blockiert ist, bis die Inhaltszeichenfolge verfügbar ist. In einem "realen" Szenario würden Sie die Aufgabe jedoch wahrscheinlich an etwas anderes übergeben oder ein anderes ContinueWith oder etwas anderes ausgeben.

void Main()
{
    var task = MakeAsyncRequest("http://www.google.com", "text/html");
    Console.WriteLine ("Got response of {0}", task.Result);
}

// Define other methods and classes here
public static Task<string> MakeAsyncRequest(string url, string contentType)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.ContentType = contentType;
    request.Method = WebRequestMethods.Http.Get;
    request.Timeout = 20000;
    request.Proxy = null;

    Task<WebResponse> task = Task.Factory.FromAsync(
        request.BeginGetResponse,
        asyncResult => request.EndGetResponse(asyncResult),
        (object)null);

    return task.ContinueWith(t => ReadStreamFromResponse(t.Result));
}

private static string ReadStreamFromResponse(WebResponse response)
{
    using (Stream responseStream = response.GetResponseStream())
    using (StreamReader sr = new StreamReader(responseStream))
    {
        //Need to return this response 
        string strContent = sr.ReadToEnd();
        return strContent;
    }
}
41
James Manning

"Noch besser wäre es, zu HttpClient zu wechseln, wenn Sie .NET 4.5 verwenden, da es" nativ "asynchron ist." - absolut richtige Antwort von James Manning ... Diese Frage wurde vor ungefähr 2 Jahren gestellt. Jetzt haben wir .NET Framework 4.5, das leistungsstarke asynchrone Methoden bietet. Verwenden Sie HttpClient. Betrachten Sie den folgenden Code:

 async Task<string> HttpGetAsync(string URI)
    {
        try
        {
            HttpClient hc = new HttpClient();
            Task<Stream> result = hc.GetStreamAsync(URI);

            Stream vs = await result;
            StreamReader am = new StreamReader(vs);

            return await am.ReadToEndAsync();
        }
        catch (WebException ex)
        {
            switch (ex.Status)
            {
                case WebExceptionStatus.NameResolutionFailure:
                    MessageBox.Show("domain_not_found", "ERROR",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                break;
                    //Catch other exceptions here
            }
        }
    }

Erstellen Sie für die Verwendung von HttpGetAsync () eine neue Methode, die ebenfalls "async" ist. async ist erforderlich, da in der GetWebPage () - Methode "waitit" verwendet werden muss:

async void GetWebPage(string URI)
        {
            string html = await HttpGetAsync(URI);
            //Do other operations with html code
        }

Wenn Sie nun den HTML-Quellcode der Webseite asynchron abrufen möchten, rufen Sie einfach GetWebPage ("Web-Adresse ...") auf. Auch das Lesen von Streams ist asynchron.

HINWEIS: Um das HttpClient .NET Framework 4.5 verwenden zu können, ist es erforderlich. Außerdem müssen Sie in Ihrem Projekt eine System.Net.Http-Referenz hinzufügen und auch "using System.Net.Http" für den einfachen Zugriff hinzufügen.

Weitere Informationen dazu, wie dieser Ansatz funktioniert, finden Sie unter: http://msdn.Microsoft.com/en-us/library/hh191443(v=vs.110).aspx

Verwendung von Async: Async in 4.5: Die Erwartung wert

6
mirushaki

Sobald Sie asynchron gehen, können Sie nie mehr zurückkehren. Von dort aus haben Sie nur noch Zugriff auf den Rückruf des Asynchronen. Sie können die Komplexität erhöhen und einige Threading- und Waithandles ausführen, aber das kann ein schmerzhaftes Unterfangen sein.

Technisch gesehen können Sie den Thread auch in den Ruhezustand versetzen, wenn Sie auf die Ergebnisse warten müssen. Ich empfehle Ihnen jedoch nicht, Sie können an diesem Punkt auch eine normale http-Anfrage ausführen.

In C # 5 haben sie async/await-Befehle, die es einfacher machen, die Ergebnisse des asynchronen Aufrufs an den Haupt-Thread zu übergeben.

2
Thinking Sites
public static async Task<byte[]> GetBytesAsync(string url) {
    var request = (HttpWebRequest)WebRequest.Create(url);
    using (var response = await request.GetResponseAsync())
    using (var content = new MemoryStream())
    using (var responseStream = response.GetResponseStream()) {
        await responseStream.CopyToAsync(content);
        return content.ToArray();
    }
}

public static async Task<string> GetStringAsync(string url) {
    var bytes = await GetBytesAsync(url);
    return Encoding.UTF8.GetString(bytes, 0, bytes.Length);
}
0
dragansr