2012-05-12 13 views
16

Zastanawiam się, czy istnieje prosty sposób uzyskania odpowiedzi asynchronicznego httpwebrequest.Uzyskiwanie odpowiedzi asynchronicznego HttpWebRequest

Widziałem już to pytanie here, ale ja je wszystkie próbuję zrobić, to zwrócić odpowiedź (która jest zwykle json lub xml) w postaci ciągu do innej metody, gdzie mogę go następnie analizować/radzić sobie z nim odpowiednio.

Herezje niektóre kod:

mam te dwie metody statyczne tutaj co moim zdaniem jest wątek bezpieczne, jak wszystkie params przechodzą i nie istnieją żadne wspólne zmienne lokalne, że metody używają?

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; 
    } 
} 
+0

Kod zostanie zaksięgowana działało dobrze raz usunąłem obcych manualResetEvent.Zestaw(); - Jaki masz problem? –

+0

@JamesManning Cześć, to był literówka, szukam łatwiejszego sposobu na uzyskanie wyniku. To, co podałeś (zadanie ) jest dokładnie wzdłuż linii. Właśnie wykonałem skok z synchronicznych żądań, wygląda na to, że jest dużo więcej. Dzięki – gdp

Odpowiedz

38

Zakładając, że problem polega na tym, że trudno jest Ci dotrzeć do zwróconej treści, najprostsza ścieżka najprawdopodobniej będzie korzystała z asynchronizacji/czekania, jeśli możesz z niego korzystać. Jeszcze lepiej byłoby przejść do HttpClient, jeśli używasz .NET 4.5, ponieważ jest on "natywnie" asynchroniczny.

Korzystając z .NET 4 i C# 4, nadal można użyć zadania, aby je opakować i ułatwić dostęp do końcowego wyniku. Na przykład jedną z opcji będzie poniższa. Zauważ, że ma on główną metodę blokowania, dopóki ciąg zawartości nie będzie dostępny, ale w "prawdziwym" scenariuszu prawdopodobnie przekażesz zadanie do czegoś innego lub wypniesz inne ContinueWith z niego lub cokolwiek innego.

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; 
    } 
} 
+0

Jeszcze raz dziękuję za odpowiedź i godzinę. – gdp

+0

Szybkie pytanie, podczas uzyskiwania dostępu do metod MakeAsyncRequest() Właściwość wyników, jak mogę upewnić się, że wynik jest zawsze zakończony do czasu i spróbować użyć odpowiedzi. – gdp

+0

Właściwość Wynik zostanie zablokowana, dopóki nie zostanie wykonana, jeśli jeszcze jej nie ma. –

2

Gdy przejdziesz do asynchronizacji, nigdy nie będziesz mógł wrócić. Stamtąd masz tylko dostęp do wywołania zwrotnego asynchronicznego. możesz zwiększyć złożoność tego i zrobić kilka wątków, ale to może być raczej bolesne przedsięwzięcie.

Technicznie, możesz również przespać wątek, gdy musisz poczekać na wyniki, ale nie polecam, możesz równie dobrze wykonać zwykłe żądanie http w tym punkcie.

W języku C# 5 mają asynchroniczne/oczekujące polecenia, które ułatwią uzyskanie wyników asynchronicznego wywołania głównego wątku.

+0

nawlekanie jest tym, co muszę zrozumieć. Dzięki za wkład. – gdp

5

"Jeszcze lepiej byłoby przejść do HttpClient, jeśli używasz .NET 4.5, ponieważ jest to" natywnie "asynchroniczne." - absolutnie słuszna odpowiedź Jamesa Manninga. To pytanie zadano około 2 lata temu. Teraz mamy platformę .NET 4.5, która zapewnia potężne asynchroniczne metody. Użyj HttpClient. Rozważmy następujący kod:

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 
      } 
     } 
    } 

Aby korzystać HttpGetAsync(), utworzyć nową metodę, która jest „asynchroniczny” też. asynchroniczny jest wymagane, ponieważ musimy użyć „czekają” w GetWebPage() metoda:

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

Teraz, jeśli chcesz dostać strony internetowej kod źródłowy html asynchronicznie, po prostu zadzwoń GetWebPage ("adres internetowy ... "). Nawet czytanie strumienia jest asynchroniczne.

UWAGA: do korzystania z HttpClient .NET Framework 4.5 jest wymagany. Musisz również dodać odniesienie System.Net.Http w swoim projekcie i dodać również "using System.Net.Http" dla łatwego dostępu.

Dla dalszego czytania, jak działa to podejście pod adresem: http://msdn.microsoft.com/en-us/library/hh191443(v=vs.110).aspx

Zastosowanie Async: Async in 4.5: Worth the Await

Powiązane problemy