2012-05-12 6 views
16

Мне интересно, есть ли простой способ получить ответ асинхронного httpwebrequest.Получение ответа от асинхронного HttpWebRequest

Я уже видел этот вопрос here, но все, что я пытаюсь сделать, это вернуть ответ (обычно json или xml) в форме строки другому методу, где я могу затем проанализировать его/обработать его соответствующим образом.

Heres некоторые код:

Я эти два статических метода здесь, которые я думаю, потокобезопасны, как все PARAMS передаются в и нет никаких общих локальных переменных, что методы используют?

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

код вы Написал работал отлично, как только я удалил посторонний ManualResetEvent.Задавать(); - В чем проблема, с которой вы сталкиваетесь? –

+0

@JamesManning Привет, это была опечатка, я получаю более простой способ получить результат. То, что вы предоставили (задание ), точно соответствует строкам. Я только что сделал прыжок от синхронных запросов, похоже, что они намного больше продолжаются. Спасибо – gdp

ответ

38

Предполагая, что проблема связана с тем, что вам трудно добраться до возвращаемого содержимого, самый простой путь, скорее всего, будет использовать async/await, если вы сможете его использовать. Еще лучше было бы переключиться на HttpClient, если вы используете .NET 4.5, так как это «изначально» async.

Используя .NET 4 и C# 4, вы все равно можете использовать Task для их переноса и упростить доступ к конечным результатам. Например, один из вариантов будет ниже. Обратите внимание, что он блокирует основной метод до тех пор, пока строка содержимого не будет доступна, но в «реальном» сценарии вы, скорее всего, передадите задачу на что-то другое или добавите другой ContinueWith от него или что-то еще.

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

Еще раз спасибо за ваш ответ и время. – gdp

+0

Быстрый вопрос при доступе к методам MakeAsyncRequest() Свойство Result, как я могу убедиться, что результат всегда будет завершен к моменту, когда я попытаюсь использовать ответ. – gdp

+0

Свойство Result будет заблокировано, пока оно не будет выполнено, если оно еще не было. –

2

Как только вы идете асинхронно, вы никогда не сможете вернуться. Оттуда вы действительно имеете доступ только к обратному вызову async. вы можете увеличить сложность этого и сделать некоторые потоки & waithandles, но это может быть довольно болезненным делом.

Технически вы можете также спящий поток, когда вам нужно ждать результатов, но я не рекомендую это делать, вы можете также выполнить обычный HTTP-запрос в этот момент.

В C# 5 они выполняют команды async/await, которые облегчат получение результатов асинхронного вызова в основной поток.

+0

Threading - это то, что мне нужно, чтобы опустить голову. Спасибо за ваш вклад. – gdp

5

«Еще лучше было бы перейти к HttpClient, если вы используете .NET 4.5, так как это„родной“асинхронной». - абсолютно правильный ответ Джеймса Мэннинга. Этот вопрос задан около 2 лет назад. Теперь у нас есть .NET framework 4.5, который предоставляет мощные асинхронные методы. Используйте HttpClient. Рассмотрим следующий код:

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

Чтобы использовать HttpGetAsync(), создайте новый метод, который «асинхронной» тоже. метод требуется асинхронная, потому что мы должны использовать «ждать» в GetWebPage():

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

Теперь, если вы хотите получить веб-страницы исходный код асинхронно, просто вызовите GetWebPage ("веб-адрес ... «). Даже чтение Считывание является асинхронным.

ПРИМЕЧАНИЕ: для использования HttpClient требуется .NET Framework 4.5. Также вам нужно добавить ссылку System.Net.Http в свой проект и добавить также «using System.Net.Http» для удобства доступа.

Для дальнейшего чтения, как работает этот подход, по адресу: http://msdn.microsoft.com/en-us/library/hh191443(v=vs.110).aspx

Использование Async: Async in 4.5: Worth the Await

Смежные вопросы