Jak używać HttpWebRequest (. NET) asynchronicznie?
Jak mogę używać HttpWebRequest (. Net, C#) asynchronicznie?
8 answers
Użycie HttpWebRequest.BeginGetResponse()
HttpWebRequest webRequest;
void StartWebRequest()
{
webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), null);
}
void FinishWebRequest(IAsyncResult result)
{
webRequest.EndGetResponse(result);
}
Funkcja wywołania zwrotnego jest wywoływana po zakończeniu operacji asynchronicznej. Musisz chociaż zadzwonić.EndGetResponse()
z tej funkcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-27 20:12:07
Rozważając odpowiedź:
HttpWebRequest webRequest;
void StartWebRequest()
{
webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), null);
}
void FinishWebRequest(IAsyncResult result)
{
webRequest.EndGetResponse(result);
}
Możesz wysłać wskaźnik żądania lub dowolny inny obiekt podobny do tego:
void StartWebRequest()
{
HttpWebRequest webRequest = ...;
webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), webRequest);
}
void FinishWebRequest(IAsyncResult result)
{
HttpWebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result) as HttpWebResponse;
}
Pozdrowienia
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-13 22:31:56
Do tej pory wszyscy się mylili, ponieważ BeginGetResponse()
trochę pracuje nad bieżącym wątkiem. Z dokumentacji :
Metoda BeginGetResponse wymaga pewnych zadań konfiguracji synchronicznej do kompletne (rozdzielczość DNS, wykrywanie proxy i połączenie z gniazdem TCP, na przykład) zanim ta metoda stanie się asynchroniczna. W rezultacie, ta metoda nigdy nie powinna być wywoływana w wątku interfejsu użytkownika (UI) ponieważ może to zająć sporo czasu (do kilku minut w zależności od ustawień sieci), aby zakończyć początkową synchronizację ustawianie zadań przed wyrzuceniem wyjątku dla błędu lub metoda / align = "left" /
Więc zrobić to dobrze:
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);
}
Możesz wtedy zrobić to, co musisz z odpowiedzią. Na przykład:
HttpWebRequest request;
// init your request...then:
DoWithResponse(request, (response) => {
var body = new StreamReader(response.GetResponseStream()).ReadToEnd();
Console.Write(body);
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-20 00:09:23
Najprostszym sposobem jest użycie TaskFactory.FromAsync z TPL . Jest to dosłownie kilka linijek kodu w połączeniu z nowymi asynchronicznymi/oczekującymi słowami kluczowymi:
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);
Jeśli nie możesz użyć kompilatora C#5, to powyższe można wykonać za pomocą zadania .ContinueWith metoda:
Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse,
request.EndGetResponse,
null)
.ContinueWith(task =>
{
var response = (HttpWebResponse) task.Result;
Debug.Assert(response.StatusCode == HttpStatusCode.OK);
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-11 05:15:07
Skończyłem z użyciem BackgroundWorker, jest zdecydowanie asynchroniczny w przeciwieństwie do niektórych z powyższych rozwiązań, obsługuje powrót do wątku GUI dla Ciebie i jest bardzo łatwy do zrozumienia.
Obsługa wyjątków jest również bardzo łatwa, ponieważ kończą się one w metodzie RunWorkerCompleted, ale upewnij się, że przeczytałeś to: nieobsługiwane wyjątki w BackgroundWorker
Użyłem WebClient, ale oczywiście można użyć HttpWebRequest.GetResponse jeśli chcesz.
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();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:23
. NET zmienił się od czasu opublikowania wielu z tych odpowiedzi i chciałbym podać bardziej aktualną odpowiedź. Użyj metody asynchronicznej, aby uruchomić Task
, która będzie działać w tle wątku:
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;
}
Aby użyć metody asynchronicznej:
String response = await MakeRequestAsync("http://example.com/");
Update:
To rozwiązanie nie działa dla aplikacji UWP, które używają WebRequest.GetResponseAsync()
zamiast WebRequest.GetResponse()
, i nie wywołuje metod Dispose()
tam, gdzie jest to właściwe. @dragansr ma dobre alternatywne rozwiązanie, które rozwiązuje te problemy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-13 15:52:49
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);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-08 06:02:34
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);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-12 11:47:29