2008-10-14 21 views
138

HttpWebRequest (.NET, C#) eşzamansız olarak nasıl kullanabilirim?HttpWebRequest (.NET) eşzamansız olarak nasıl kullanılır?

+1

kullanım:

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öntemini kullanmak için: Bir arka plan iş parçacığı üzerinde çalışacak bir Task başlatmak için bir zaman uyumsuz yöntemini kullanın /library/system.net.webrequest.endgetrequeststream.aspx –

+1

Bir an için, özyinelemeli bir konu üzerine yorum yapmaya çalışıp çalışmadığınızı merak ettim? –

+0

Ayrıca, Jason'ın sorduğu şeyi yapmanın tam bir örneği için aşağıdakileri de görebilirsiniz: http://stuff.seans.com/2009/01/05/using-httpwebrequest-for-asynchronous-downloads/ Sean –

cevap

115

Kullanım HttpWebRequest.BeginGetResponse()

HttpWebRequest webRequest; 

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

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

uyumsuz işlem tamamlandığında geri çağırma işlevi çağrılır. Bu işlevden en azından EndGetResponse()'u aramanız gerekir. ,

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

+12

BeginGetResponse, async kullanımı için yararlı değildir. Kaynakla bağlantı kurmaya çalışırken engelleniyor gibi görünüyor. Ağ kablosunu çıkarmayı veya hatalı biçimlendirilmiş bir uri yapmayı ve sonra bu kodu çalıştırmayı deneyin. Bunun yerine, muhtemelen GetResponse'yi sağladığınız ikinci bir thread üzerinde çalıştırmanız gerekir. – Ash

+2

@AshleyHenderson - Bana bir örnek verebilir misiniz? – Tohid

+0

@Tohid [burada örnekle dolu bir sınıf var] (http://stackoverflow.com/questions/12224602/a-method-for-making-http-requests-on-unity-ios/12606963#12606963) Unity3D ile kullanılır. – cregox

62

cevap düşünüldüğünde BeginGetResponse(), bazı geçerli iş parçacığı üzerinde çalıştığı için. documentation Gönderen:

BeginGetResponse yöntem bu yöntem zaman uyumsuz hale gelmeden önce tamamlandı (DNS çözümlemesi, vekil algılama, ve TCP soket bağlantısı, örneğin ) bazı senkron kurulum görevlerini gerektirir. Sonuç olarak, bu yöntem hiçbir zaman kullanıcı arabirimi (UI) iş parçacığı üzerinde çağrılmamalıdır, çünkü ilk kez kurulum görevlerini tamamlamak için önemli bir süre (başlangıçtaki ağ ayarlarına bağlı olarak birkaç dakikaya kadar) kurulum görevleri Hata atılıyor veya yöntemi başarılı.

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 tepki ile gerekenleri yapabilirsiniz:

Yani bu doğru yapmak. Örneğin: Ben backgroundworker kullanarak sona erdi

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

+ 1 olduğunu söyleyen bir hata atıyor, ancak "as" anahtar sözcüğünü kullanmak yerine bir cast yapmış olabilirsiniz. Bir InvalidCastException şaşkın bir NullReferenceException yerine atılırdı. –

3
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); 
     } 
    } 
57

Herkes şimdiye kadar yanlış olmuştur:

HttpWebRequest webRequest; 

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

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

Böyle istek işaretçisi veya başka bir nesne gönderebilir:

+2

HttpWebRequest öğesinin beklemeyi kullanarak GetResponseAsync yöntemini çağırmaktan başka bir şey yapamazsınız (işlevinizi eşzamanlı yaptığınızı varsayarsak)? C# için çok yeni oldum, bu tam jibberish olabilir ... – Brad

+0

GetResponseAsync iyi görünüyor, ancak .NET 4.5'e ihtiyacınız var (şu anda beta). – Isak

+12

İsa. Bu çirkin bir kod. Neden uyumsuz kod okunamıyor? –

7

, yukarıdaki çözümlerden bazıları, sizin için GUI iplik dönen kolları aksine kesinlikle asenkron olduğunu ve anlamak çok kolaydır. Unhandled exceptions in BackgroundWorker

ben WebClient'ı kullanılan ancak isterseniz açıkçası HttpWebRequest.GetResponse kullanabilirsiniz:

Onlar RunWorkerCompleted yönteminde sona kadar, istisnalar işlemek, ancak bu okuma emin olmak için de çok kolaydır. kadar kolay arada

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(); 
47

TPL dan TaskFactory.FromAsync kullanmaktır.

: Eğer daha sonra yukarıdaki Task.ContinueWith yöntemi kullanılarak yapılabilir C 5. derleyicisi kullanamıyorsanız

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

: Yeni async/await anahtar kelimelerle birlikte kullanıldığında Tam anlamıyla satır kod buradan bir kaç

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

.NET 4'ten bu yana, bu TAP yaklaşımı tercih edilir. MS'den benzer bir örneğe bakın - "Nasıl Yapılır: Bir Görevde EAP Kalıplarını Sarma" (http://msdn.microsoft.com/en-us/library/ee622454.aspx) –

+0

Yol diğer yollardan daha kolay –

2

.Bu cevapların çoğu yayınlandığından beri NET değişti ve daha güncel bir cevap vermek istiyorum. http://msdn.microsoft.com/en-us zaman uyumsuz

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

Teşekkür ederiz! Eşsiz bir örnek bulmaya çalıştık, karmaşık olan eski yaklaşımı kullanan pek çok örnek. – WDUK

+0

Bu, her yanıt için bir iş parçacığını engelleyemez mi? örn. https://docs.microsoft.com/tr-tr/dotnet/standard/parallel-programming/how-to-wrap-eap-patterns-in-a-task –

+0

@PeteKirkham Bir arka plan iş parçacığı isteği yapıyor, değil UI iş parçacığı. Amaç, UI iş parçacığının engellenmesini önlemektir. Bir istekte bulunmayı seçtiğiniz herhangi bir yöntem, isteği yapan diziyi engeller. Başvurduğunuz Microsoft örneği, birden çok istekte bulunmaya çalışıyor, ancak istekleri için yine de bir Görev (arka plan iş parçacığı) oluşturuyorlar. – tronman

İlgili konular