Время ожидания HttpClient до указанного времени ожидания

Я использую HttpClient из WP8 и делаю запрос Post. Я знаю, что вызов может занять много времени, так как я фактически имитирую медленные сетевые сценарии. Поэтому я установил HttpClient.Timeout соответственно на 5 минут.

Тем не менее, я получаю тайм-аут около 60 с. Я считаю, что тайм-аут не работает. Я считаю, что есть проблема с этим для WP, как указано в этом вопросе: HttpClient Portable возвращает 404 notfound на WP8.

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

Мои вопросы:

1) Это ошибка/проблема HttpClient для WP8 или я неправильно его устанавливаю? 2) Вы думаете об обходном пути, все еще использующем HttpClient?

Я читал, что, возможно, HttpWebRequest является вариантом. Однако я считаю, что HttpClient должен идеально подходить для этого «простого» сценария.

Мой код прост:

private static async Task<HttpResponseMessage> PostAsync(Uri serverUri, HttpContent httpContent)
{
    var client = new HttpClient();
    client.Timeout = TimeSpan.FromMinutes(5);
    return await client.PostAsync(serverUri, httpContent).ConfigureAwait(false);
}

Сервер получает запрос и во время его обработки клиент прерывает работу.

ОБНОВЛЕНИЕ: HttpResponseMessage, возвращаемый HttpClient.PostAsyn, это "{StatusCode: 404, ReasonPhrase: '', Version: 0.0, Content: System.Net.Http.StreamContent, Headers: { Content-Length: 0 }}". Как я уже сказал, сервер найден, принимает данные и обрабатывает их.


person jbarrameda    schedule 18.04.2014    source источник
comment
Вы уверены, что сервер не отключается через 60 секунд?   -  person Eric J.    schedule 18.04.2014
comment
Да, я уверен. На самом деле я также запускаю сервер и вижу прогресс. Сервер выполняет некоторый процесс с интенсивным использованием процессора, прежде чем ответить клиенту.   -  person jbarrameda    schedule 18.04.2014


Ответы (2)


После некоторого поиска и некоторых тестов я пришел к выводу, что проблема заключается в самом Windows Phone и что он имеет тайм-аут 60 секунд (независимо от HttpClient) и, насколько мне известно, это нельзя изменить. См. http://social.msdn.microsoft.com/Forums/en-US/faf00a04-8a2e-4a64-b1c1-74c52cf685d3/httpwebrequest-60-seconds-timeout.

Поскольку я также программирую сервер, я воспользуюсь советом Дарина Руссо по приведенной выше ссылке, в частности, отправить OK, а затем выполнить дополнительную обработку.


ОБНОВЛЕНИЕ: проблема, похоже, связана с эмулятором Windows Phone, как указано здесь: httpclient-doesnt-work-on-windows-phone?forum=wpdevelop" rel="nofollow">http://social.msdn.microsoft.com/forums/wpapps/en-us/6c114ae9-4dc1-4e1f-afb2- a6b9004bf0c6/httpclient-doesnt-work-on-windows-phone?forum=wpdevelop. По моему опыту, время ожидания TCP-соединения истекает, если оно ничего не слышит в течение 60 секунд.


Поэтому мое решение состоит в том, чтобы использовать символы заголовка Http как способ поддержания активности. Ответ заголовка Http первой строки всегда начинается с HTTP/1.0. Поэтому я отправляю символы один за другим с задержкой ‹60s между ними. Конечно, если ответ будет готов, все, что осталось, будет отправлено сразу. Это позволяет выиграть время, например, если использовать задержку в 50 секунд на 9 символов, мы получим около 450 секунд.

Это проект для моей степени, поэтому я бы не рекомендовал его для производства.

Кстати, я также пробовал использовать другие символы вместо подстроки заголовка, например пробел, но это приводит к нарушению протокола http.

Это основная часть кода:

    private const string Header1 = @"HTTP/1.0 ";
    private int _keepAliveCounter = 0;
    private readonly object _sendingLock = new object();
    private bool _keepAliveDone = true;

    private void StartKeepAlive()
    {
        Task.Run(() => KeepAlive());
    }

    /// <summary>
    /// Keeps the connection alive sending the first characters of the http response with an interval.
    /// This is a hack for Windows Phone 8 that need reponses within 60s interval.
    /// </summary>
    private void KeepAlive()
    {
        try
        {
            _keepAliveDone = false;
            _keepAliveCounter = 0;
            while (!_keepAliveDone && _keepAliveCounter < Header1.Length)
            {
                Task.Delay(TimeSpan.FromSeconds(50)).Wait();
                lock (_sendingLock)
                {
                    if (!_keepAliveDone)
                    {
                        var sw = new StreamWriter(OutputStream);
                        sw.Write(Header1[_keepAliveCounter]);
                        Console.Out.WriteLine("Wrote keep alive char '{0}'", Header1[_keepAliveCounter]);
                        _keepAliveCounter++;
                        sw.Flush();
                    }
                }
            }
            _keepAliveCounter = 0;
             _keepAliveDone = true;
        }
        catch (Exception e)
        {
            // log the exception
            Console.Out.WriteLine("Error while sending keepalive: " + e.Message);
        }
    }

Затем фактическая обработка происходит в другом потоке.

Комментарии и критика приветствуются.

person jbarrameda    schedule 18.04.2014
comment
Проблема не ограничивается эмулятором Windows Phone 8. У меня проблема возникает и на реальном устройстве (Nokia Lumia 830). Я пытаюсь использовать HttpClient для отправки запроса PUT, который занимает более 60 секунд, и получаю ошибку 404. - person iupchris10; 10.09.2015
comment
Хорошо знать. (Наверное, вы установили тайм-аут более 60 секунд?) Это должно быть в переносимой реализации .Net или в ОС тоже.. Спасибо, что поделились. - person jbarrameda; 11.09.2015
comment
Да, я установил время ожидания на 10 минут, но ошибка 404 все равно выдает 60 секунд. У меня есть несколько длинных синхронных запросов, которые необходимо выполнить. Я не нашел способа увеличить время ожидания более 60 секунд. - person iupchris10; 04.11.2015

Возможно, у вас превышен тайм-аут сетевого потока. Вы можете изменить это, выполнив

var handler = new WebRequestHandler();
handler.ReadWriteTimeout= 5 * 60 * 1000;
var client = new HttpClient(handler);
client.Timeout = TimeSpan.FromMinutes(5);
return await client.PostAsync(serverUri, httpContent).ConfigureAwait(false);

По умолчанию в настольной ОС уже 5 минут. Однако не исключено, что в Windows Phone он по умолчанию уменьшен.

person Darrel Miller    schedule 18.04.2014
comment
Спасибо за ваш ответ. Я пытался, но, к сожалению, WebRequestHandler недоступен для WP. - person jbarrameda; 18.04.2014
comment
@JB Сначала я тоже так думал, однако по какой-то причине документы MSDN говорят, что это так. msdn.microsoft.com /en-us/библиотека/ - person Darrel Miller; 18.04.2014
comment
HttpClientHandler есть, но тайм-аута нет. - person jbarrameda; 18.04.2014
comment
@jb Да, HttpClientHandler является обработчиком по умолчанию. - person Darrel Miller; 18.04.2014