Получение ответа на асинхронный HttpWebRequest

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

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

Вот код:

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

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

person gdp    schedule 12.05.2012    source источник
comment
Код, который вы разместили, работал нормально, как только я удалил посторонний manualResetEvent.Set(); - какая у тебя проблема?   -  person James Manning    schedule 12.05.2012
comment
@JamesManning Привет, да, это была опечатка, мне нужен более простой способ получить результат. То, что вы предоставили (Задание‹T›), точно соответствует линиям. Я только что перешел от синхронных запросов, похоже, происходит гораздо больше. Спасибо   -  person gdp    schedule 12.05.2012


Ответы (3)


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

Используя .NET 4 и C# 4, вы по-прежнему можете использовать Task, чтобы обернуть их и немного упростить доступ к конечному результату. Например, один из вариантов будет ниже. Обратите внимание, что у него есть блокировка метода Main до тех пор, пока строка содержимого не станет доступной, но в «реальном» сценарии вы, вероятно, передадите задачу чему-то другому или настроите еще один 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;
    }
}
person James Manning    schedule 12.05.2012
comment
Еще раз спасибо за ваш ответ и время. - person gdp; 12.05.2012
comment
Быстрый вопрос: при доступе к свойству Result методов MakeAsyncRequest(), как я могу убедиться, что результат всегда будет завершен к тому времени, когда я попытаюсь использовать ответ. - person gdp; 14.05.2012
comment
Свойство Result будет заблокировано до тех пор, пока оно не будет выполнено, если это еще не сделано. - person James Manning; 14.05.2012
comment
Хорошо, отлично, поэтому запросы будут происходить асинхронно, и будет заблокировано только чтение потока. - person gdp; 15.05.2012
comment
@geepie - правильно, какой бы поток ни обращался к свойству Result (до того, как он будет готов), он будет блокироваться до тех пор, пока задача либо не завершится (и результат будет возвращен), либо не завершится (и он вызовет исключение) - person James Manning; 15.05.2012
comment
запрос.Время ожидания = 20000; бесполезен в асинхронном запросе на получение - person xiaoyifang; 24.07.2014
comment
Это не работает для меня, задача не ждет ответа, она просто работает, она должна ждать, пока не получит ответ, я вижу статус ответа WaitingToActivation. - person Ashish-BeJovial; 16.10.2014

Еще лучше было бы переключиться на HttpClient, если вы используете .Net 4.5, так как он "изначально" async. - абсолютно правильный ответ Джеймса Мэннинга.

Этот вопрос был задан около 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(), создайте новый асинхронный метод. async требуется, потому что нам нужно использовать await в методе GetWebPage():

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

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

ПРИМЕЧАНИЕ: для использования 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: Асинхронизация в версии 4.5: стоит подождать

person mirushaki    schedule 01.09.2014

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

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

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

person Thinking Sites    schedule 12.05.2012
comment
резьба - это то, что у меня есть, чтобы разобраться. Спасибо за ваш вклад. - person gdp; 12.05.2012