Как реализовать отчеты о ходе выполнения для Portable HttpClient

Я пишу библиотеку с намерением использовать ее в приложениях для настольных компьютеров (.Net 4.0 и выше), телефонах (WP 7.5 и выше) и Магазине Windows (Windows 8 и выше).

Библиотека имеет возможность загружать файлы из Интернета с помощью библиотеки Portable HttpClient и сообщать о ходе загрузки.

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

Есть ли у кого-нибудь статья, документация, руководство, пример кода или что-то еще, что поможет мне в этом?


person TheBlueSky    schedule 16.01.2014    source источник


Ответы (2)


Я написал следующий код для реализации отчетов о ходе выполнения. Код поддерживает все платформы, которые я хотел; однако вам необходимо сослаться на следующие пакеты NuGet:

  • Microsoft.Net.Http
  • Microsoft.Bcl.Async

Вот код:

public async Task DownloadFileAsync(string url, IProgress<double> progress, CancellationToken token)
{
    var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);

    if (!response.IsSuccessStatusCode)
    {
        throw new Exception(string.Format("The request returned with HTTP status code {0}", response.StatusCode));
    }

    var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
    var canReportProgress = total != -1 && progress != null;

    using (var stream = await response.Content.ReadAsStreamAsync())
    {
        var totalRead = 0L;
        var buffer = new byte[4096];
        var isMoreToRead = true;

        do
        {
            token.ThrowIfCancellationRequested();

            var read = await stream.ReadAsync(buffer, 0, buffer.Length, token);

            if (read == 0)
            {
                isMoreToRead = false;
            }
            else
            {
                var data = new byte[read];
                buffer.ToList().CopyTo(0, data, 0, read);

                // TODO: put here the code to write the file to disk

                totalRead += read;

                if (canReportProgress)
                {
                    progress.Report((totalRead * 1d) / (total * 1d) * 100);
                }
            }
        } while (isMoreToRead);
    }
}

Использование его так же просто, как:

var progress = new Microsoft.Progress<double>();
progress.ProgressChanged += (sender, value) => System.Console.Write("\r%{0:N0}", value);

var cancellationToken = new CancellationTokenSource();

await DownloadFileAsync("http://www.dotpdn.com/files/Paint.NET.3.5.11.Install.zip", progress, cancellationToken.Token);
person TheBlueSky    schedule 08.02.2014
comment
Я знаю, что это своего рода некрокомментарии, но я просто хотел бы добавить, что я использовал этот подход и столкнулся с проблемами синхронизации, когда было так много вывода прогресса, что он отставал от фактического хода загрузки, что приводило к файл загружается намного быстрее, чем сообщается о прогрессе. (В итоге я использовал секундомер, чтобы отчитываться только каждую секунду или около того) - person Dynde; 13.03.2017
comment
Не уверен, что могло вызвать это. Я обнаружил, что это хорошо работает в моем сценарии; в том числе с использованием буфера размером 4096 байт. - person TheBlueSky; 17.03.2017
comment
Что означает put here the code to write the file to disk? Я предположил, что вы имеете в виду the data, но какие данные и как их записать? Я добавляю его в файл или записываю все сразу? - person ProfK; 30.03.2018
comment
@ProfK data — это массив байтов, содержащий точные байты, которые были прочитаны. Да, вы продолжаете добавлять его в файл, пока не будет прочитан последний байт. - person TheBlueSky; 30.03.2018

Вы можете указать HttpCompletionOption.ResponseHeadersRead, а затем получить поток и сообщить о ходе выполнения во время чтения из потока. См. похожий вопрос.

person TheESJ    schedule 17.01.2014
comment
может быть похоже, но не ответ на мой вопрос, как есть. Но спасибо за ссылку, она помогла мне найти ответ. - person TheBlueSky; 08.02.2014