Асинхронное выполнение http запросов

Есть у меня синхронный http запрос, и он прекрасно работает:

private string zaproshttp(string sURL)
{
    WebRequest wrGETURL = WebRequest.Create(sURL);
    Stream objStream = null;
    try
    {
        objStream = wrGETURL.GetResponse().GetResponseStream();
    }
    catch
    { 
        Обработка ошибок...
    }
    StreamReader objReader = new StreamReader(objStream);   
    return objReader.ReadLine());
}

Но тут возникает проблема, иногда ответ от сервера долго не приходит, и программа подвисает. В принципе ничего страшного в этом нет, без ответа сервера смысла в работе программы нет. Но пользователи часто не дожидаются ответа, т.к. думают, что программа зависла. В голову пришла идея, сделать http запрос асинхронным, а в основном пакете крутить Гифку, типа ждите... (в синхронном режиме программа висит и гифка не крутится). Вот код подсмотренный в просторах тырнета:

private async Task<string> zaproshttp2(string sURL )
{
    HttpWebRequest request = WebRequest.CreateHttp(sURL);
    request.Method = "GET";
    using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync())
    {
        using (StreamReader reader = new StreamReader(response.GetResponseStream()))
        {
            return reader.ReadLine();
        }
    }
}

И этот код наглухо зависает на using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync()) Как я понимаю, запрос выполняется, но код дальше не работает. Пробовал через другие способы, так же зависает. В чем проблема, куда копать?


Ответы (1 шт):

Автор решения: aepot

код наглухо зависает - это верятно дедлок и вам надо было вместо return reader.ReadLine(); делать return await reader.ReadLineAsync(); хотя в данном случае наверное всё-таки reader.ReadToEndAsync().

WebRequest устарел очень давно, используйте HttpClient, он сам по себе асинхронный.

// HttpClient создается один раз на всё время работы приложения
private static readonly HttpClient client = new HttpClient();

private async Task<string> HttpRequest(string url)
{
    try
    {
        return await client.GetStringAsync(url).ConfigureAwait(false);
    }
    catch (Exception ex)
    { 
        // ex.Message
    }
    return null;
}

Если нужно вернуть ответ даже если сервер ответил ошибкой (код выше бросит исключение), то можно написать так:

private async Task<string> HttpRequest(string url)
{
    try
    {
        using (HttpResponseMessage response = await client.GetAsync(url).ConfigureAwait(false))
        {
            return await response.ReadAsStringAsync();
        }
    }
    catch (Exception ex)
    { 
        // ex.Message
    }
    return null;
}

В C# названия методов пишутся с большой буквы.


string responseText = await HttpRequest("https://example.ru");
→ Ссылка