Побайтовое считывание потока, полученного из HttpContent - C#
Формулировка задачи:
Доброго времени суток, Господа.
Подскажите пожалуйста, у меня делается Get запрос с помощью Вопрос #1: Что произойдет, если после получения ответа, но до получения потока, выключится интернет? Я лично никак не могу этот момент отладить. При любом исходе, я получаю поток.
Теперь продолжим. После получения потока, я его начинаю считывать в другой поток:Если я выключаю интернет, то у меня происходит остановка на чтении и больше не продолжается. При подключении интернета, закачка не продолжается. Мало того, он все равно ожидает
Устанавливаю это значение, там например 3000 миллисек, все равно ожидает чтения до бесконечности. Бред какой-то
Тоесть только синхронный вызов Итак, он запускаем два Task(один основной, другой задержка по времени таймаута с отменой), и ждем завершения Может кому пригодиться. Другого решения я не нашел
HttpClient
, в параметре которого я устанавливаю HttpCompletionOption.ResponseHeadersRead
, чтобы не ждать контент, а получить только заголовки.
Итак, после того как я получаю ответ, я из его контента получаю поток:var stream = await response.Content.ReadAsStreamAsync()
while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) != 0) { await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken); totalBytesRead += bytesRead; progress.Report(totalBytesRead); }
bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken)
!! Ни исключения, ничего не выдает. Таймауты уже все перепробовал выставлять, один фиг стоит на этой строчке и все.
Подскажите пожалуйста, как решить этот вопрос?
На MSDN написано про
ReadTimeout
:
A Int32 задает временной интервал, в миллисекундах, по истечении которого происходит сбой операции чтения. Значение по умолчанию, Infinite, указывает, что операция чтения не простаивает.
Короче, делюсь знаниями, как решить данную проблему.
Итак, по моей невнимательности, про
ReadTimeout
на MSDN еще написано вот что:
Это свойство влияет только синхронных операций чтения, выполненных вызова Read метод. Это свойство не влияет на асинхронного считывания путем вызова BeginRead метод.
stream.Read(buffer, 0, buffer.Length)
сбросится в том случае если ReadTimeout
не Infinite! А асинхронной await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken)
не сбросится ни при каком значении ReadTimeout
.
Не знаю зачем Microsoft так сделали, но я решил проблему за счет введения ручного Timeout'а.
Итак, написал вот такой Extention для Task:public static async TaskTimeoutAfter (this Task task, TimeSpan timeout) { using (var timeoutCancellationTokenSource = new CancellationTokenSource()) { var completedTask = await Task.WhenAny(task, Task.Delay(timeout, timeoutCancellationTokenSource.Token)); if(completedTask == task) { timeoutCancellationTokenSource.Cancel(); return await task; } else throw new TimeoutException("The operation has timed out."); } }
хоть одного
из них. В случае если выполнился первым основной Task, то кидаем отмену на Task-таймаут, и все. А случае, если выполнился первым Task-таймаут, то кидаем исключениеTimeoutException
. Все
Применение на моем коде:try { while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length).TimeoutAfter(new TimeSpan(0, 0, 3))) != 0) { destination.Write(buffer, 0, bytesRead); totalBytesRead += bytesRead; progress.Report(totalBytesRead); } } catch(TimeoutException e) { // Ура, мы сбросили чтение по таймауту }
Решение задачи: «Побайтовое считывание потока, полученного из HttpContent»
textual
Листинг программы
var response = await client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead); // Проверяем статус ответа switch (response.StatusCode) { case HttpStatusCode.NotFound: throw new ResourceNotFoundException(MessageError.NOT_FOUND_ERROR); case HttpStatusCode.Unauthorized: throw new AuthErrorException(MessageError.AUTH_ERROR); }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д