HttpWebRequest (.NET, C #) zaman uyumsuz olarak nasıl kullanabilirim?
HttpWebRequest (.NET, C #) zaman uyumsuz olarak nasıl kullanabilirim?
Yanıtlar:
kullanım HttpWebRequest.BeginGetResponse()
HttpWebRequest webRequest;
void StartWebRequest()
{
webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), null);
}
void FinishWebRequest(IAsyncResult result)
{
webRequest.EndGetResponse(result);
}
Eşzamansız işlem tamamlandığında geri arama işlevi çağrılır. En azından EndGetResponse()
bu işlevden çağrı yapmanız gerekir .
webRequest.Proxy = null
İsteği önemli ölçüde hızlandırmak için eklemeniz gerekir .
Cevap göz önüne alındığında:
HttpWebRequest webRequest;
void StartWebRequest()
{
webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), null);
}
void FinishWebRequest(IAsyncResult result)
{
webRequest.EndGetResponse(result);
}
İstek işaretçisini veya bunun gibi başka bir nesneyi gönderebilirsiniz:
void StartWebRequest()
{
HttpWebRequest webRequest = ...;
webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), webRequest);
}
void FinishWebRequest(IAsyncResult result)
{
HttpWebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result) as HttpWebResponse;
}
Selamlar
Şimdiye kadar herkes yanlış, çünkü BeginGetResponse()
mevcut konu üzerinde çalışıyor. Gönderen belgeler :
BeginGetResponse yöntemi, bu yöntem eşzamansız hale gelmeden önce tamamlanması için bazı eşzamanlı kurulum görevleri gerektirir (örneğin DNS çözümlemesi, proxy algılama ve TCP soket bağlantısı). Sonuç olarak, bu yöntem hiçbir zaman bir kullanıcı arabirimi (UI) iş parçacığında çağrılmamalıdır çünkü bir hata istisnası atılmadan önce ilk eşzamanlı kurulum görevlerinin tamamlanması uzun sürebilir (ağ ayarlarına bağlı olarak birkaç dakikaya kadar sürebilir) veya yöntem başarılı olur.
Bunu doğru yapmak için:
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);
}
Daha sonra yanıtla ihtiyacınız olanı yapabilirsiniz. Örneğin:
HttpWebRequest request;
// init your request...then:
DoWithResponse(request, (response) => {
var body = new StreamReader(response.GetResponseStream()).ReadToEnd();
Console.Write(body);
});
Bugüne kadar en kolay yolu kullanmaktır TaskFactory.FromAsync gelen VUK . Yeni zaman uyumsuz / beklemedeki anahtar kelimelerle birlikte kullanıldığında, kelimenin tam anlamıyla birkaç kod satırı vardır :
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);
C # 5 derleyicisini kullanamıyorsanız yukarıdaki işlem Task.ContinueWith yöntemi kullanılarak gerçekleştirilebilir :
Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse,
request.EndGetResponse,
null)
.ContinueWith(task =>
{
var response = (HttpWebResponse) task.Result;
Debug.Assert(response.StatusCode == HttpStatusCode.OK);
});
BackgroundWorker kullanarak sona erdi, yukarıdaki çözümlerin bazılarının aksine kesinlikle asenkron, sizin için GUI iş parçacığına dönen kolları ve anlaşılması çok kolay.
İstisnaları işlemek de çok kolaydır, çünkü bunlar RunWorkerCompleted yönteminde bulunur, ancak bunu okuduğunuzdan emin olun: BackgroundWorker'da işlenmeyen istisnalar
WebClient kullandım ama isterseniz HttpWebRequest.GetResponse'yi kullanabilirsiniz.
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();
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);
}
Bu yanıtların çoğunun gönderilmesinden bu yana .NET değişti ve daha güncel bir yanıt vermek istiyorum. Task
Bir arka plan iş parçacığında çalışacak olanı başlatmak için zaman uyumsuz bir yöntem kullanın :
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;
}
Zaman uyumsuz yöntemi kullanmak için:
String response = await MakeRequestAsync("http://example.com/");
Güncelleme:
Bu çözüm, WebRequest.GetResponseAsync()
yerine kullanılan UWP uygulamaları WebRequest.GetResponse()
için çalışmaz ve Dispose()
uygun olan yerlerde yöntemleri çağırmaz . @dragansr bu sorunları ele alan iyi bir alternatif çözüme sahiptir.
WebRequest.GetResponseAsync()
ve StreamReader.ReadToEndAync()
kullanılması ve beklenmesi gerekir.
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);
}
}