Frage

Wie kann ich HttpWebRequest (.NET, C #) asynchron?

War es hilfreich?

Lösung

Verwenden Sie HttpWebRequest.BeginGetResponse()

HttpWebRequest webRequest;

void StartWebRequest()
{
    webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), null);
}

void FinishWebRequest(IAsyncResult result)
{
    webRequest.EndGetResponse(result);
}

Die Callback-Funktion wird aufgerufen, wenn der asynchrone Vorgang abgeschlossen ist. Sie müssen zumindest anrufen EndGetResponse() von diesem Funktion.

Andere Tipps

In Anbetracht der Antwort:

HttpWebRequest webRequest;

void StartWebRequest()
{
    webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), null);
}

void FinishWebRequest(IAsyncResult result)
{
    webRequest.EndGetResponse(result);
}

Sie können den Antrag Zeiger oder ein anderes Objekt wie folgt an:

void StartWebRequest()
{
    HttpWebRequest webRequest = ...;
    webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), webRequest);
}

void FinishWebRequest(IAsyncResult result)
{
    HttpWebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result) as HttpWebResponse;
}

Grüße

Jeder bisher falsch gewesen, weil BeginGetResponse() einige Arbeit auf dem aktuellen Thread tut. Von der Dokumentation :

  

Die BeginGetResponse Methode erfordert einige synchrone Setup-Aufgaben   vollständige (DNS-Auflösung, Proxy-Erkennung, und TCP-Socket-Verbindung,   zum Beispiel), bevor diese Methode asynchron wird. Als Ergebnis,   Diese Methode sollte nie auf einer Benutzeroberfläche (UI) Thread aufgerufen werden   weil es viel Zeit bis zu mehreren Minuten könnte dauern (bis   auf Netzwerkeinstellungen abhängig) die anfängliche synchron zu vervollständigen   Setup-Aufgaben vor einer Ausnahme für einen Fehler ausgelöst werden, oder das Verfahren,   erfolgreich ist.

So, dieses Recht zu tun:

void DoWithResponse(HttpWebRequest request, Action<HttpWebResponse> responseAction)
{
    Action wrapperAction = () =>
    {
        request.BeginGetResponse(new AsyncCallback((iar) =>
        {
            var response = (HttpWebResponse)((HttpWebRequest)iar.AsyncState).EndGetResponse(iar);
            responseAction(response);
        }), request);
    };
    wrapperAction.BeginInvoke(new AsyncCallback((iar) =>
    {
        var action = (Action)iar.AsyncState;
        action.EndInvoke(iar);
    }), wrapperAction);
}

Sie können dann tun, was Sie mit der Antwort müssen. Zum Beispiel:

HttpWebRequest request;
// init your request...then:
DoWithResponse(request, (response) => {
    var body = new StreamReader(response.GetResponseStream()).ReadToEnd();
    Console.Write(body);
});

Bei weitem der einfachste Weg ist die Verwendung von TaskFactory.FromAsync aus dem TPL . Es ist buchstäblich ein paar Zeilen Code, wenn sie in Verbindung mit dem neuen async / await keywords:

var request = WebRequest.Create("http://www.stackoverflow.com");
var response = (HttpWebResponse) await Task.Factory
    .FromAsync<WebResponse>(request.BeginGetResponse,
                            request.EndGetResponse,
                            null);
Debug.Assert(response.StatusCode == HttpStatusCode.OK);

Wenn Sie nicht die C # 5 Compiler verwenden, dann kann die oben erreicht werden, mit der Task.ContinueWith Methode:

Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse,
                                    request.EndGetResponse,
                                    null)
    .ContinueWith(task =>
    {
        var response = (HttpWebResponse) task.Result;
        Debug.Assert(response.StatusCode == HttpStatusCode.OK);
    });

Ich landete mit Background, es ist auf jeden Fall asynchron im Gegensatz zu einigen der oben genannten Lösungen, um es für Sie den GUI-Thread Griffe Rückkehr und es ist sehr leicht zu verstehen.

Es ist auch sehr einfach, Ausnahmen zu behandeln, wie sie in der RunWorkerCompleted Methode am Ende, aber stellen Sie sicher, dass Sie lesen Sie diese: Unbehandelte Ausnahmen in Background

Ich habe WebClient aber offensichtlich konnte man HttpWebRequest.GetResponse verwenden, wenn man will.

var worker = new BackgroundWorker();

worker.DoWork += (sender, args) => {
    args.Result = new WebClient().DownloadString(settings.test_url);
};

worker.RunWorkerCompleted += (sender, e) => {
    if (e.Error != null) {
        connectivityLabel.Text = "Error: " + e.Error.Message;
    } else {
        connectivityLabel.Text = "Connectivity OK";
        Log.d("result:" + e.Result);
    }
};

connectivityLabel.Text = "Testing Connectivity";
worker.RunWorkerAsync();

.NET hat sich geändert seit dem wurden viele dieser Antworten geschrieben, und ich möchte eine mehr up-to-date schaffen Antwort. Verwenden Sie eine Asynchron-Methode, um ein Task zu starten, die auf einem Hintergrund-Thread ausgeführt werden:

private async Task<String> MakeRequestAsync(String url)
{    
    String responseText = await Task.Run(() =>
    {
        try
        {
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            WebResponse response = request.GetResponse();            
            Stream responseStream = response.GetResponseStream();
            return new StreamReader(responseStream).ReadToEnd();            
        }
        catch (Exception e)
        {
            Console.WriteLine("Error: " + e.Message);
        }
        return null;
    });

    return responseText;
}

von der Asynchron-Methode verwenden:

String response = await MakeRequestAsync("http://example.com/");

Update:

Diese Lösung nicht für UWP-Anwendungen arbeiten, die WebRequest.GetResponseAsync() anstelle von WebRequest.GetResponse(), und es stellt nicht die Dispose() Methoden gegebenenfalls. @dragansr hat eine gute alternative Lösung, die diese Fragen behandelt werden.

public void GetResponseAsync (HttpWebRequest request, Action<HttpWebResponse> gotResponse)
    {
        if (request != null) { 
            request.BeginGetRequestStream ((r) => {
                try { // there's a try/catch here because execution path is different from invokation one, exception here may cause a crash
                    HttpWebResponse response = request.EndGetResponse (r);
                    if (gotResponse != null) 
                        gotResponse (response);
                } catch (Exception x) {
                    Console.WriteLine ("Unable to get response for '" + request.RequestUri + "' Err: " + x);
                }
            }, null);
        } 
    }
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);
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top