Побайтовое считывание потока, полученного из HttpContent - C#

Узнай цену своей работы

Формулировка задачи:

Доброго времени суток, Господа. Подскажите пожалуйста, у меня делается Get запрос с помощью HttpClient, в параметре которого я устанавливаю HttpCompletionOption.ResponseHeadersRead, чтобы не ждать контент, а получить только заголовки. Итак, после того как я получаю ответ, я из его контента получаю поток:
var stream = await response.Content.ReadAsStreamAsync()
Вопрос #1: Что произойдет, если после получения ответа, но до получения потока, выключится интернет? Я лично никак не могу этот момент отладить. При любом исходе, я получаю поток. Теперь продолжим. После получения потока, я его начинаю считывать в другой поток:
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, указывает, что операция чтения не простаивает.
Устанавливаю это значение, там например 3000 миллисек, все равно ожидает чтения до бесконечности. Бред какой-то
Короче, делюсь знаниями, как решить данную проблему. Итак, по моей невнимательности, про
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 Task TimeoutAfter(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-таймаут, и все. А случае, если выполнился первым 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);
}

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

5   голосов , оценка 3.4 из 5
Похожие ответы