Страницы

Поиск по вопросам

суббота, 21 декабря 2019 г.

C# Неконтролируемое обновление консольного прогрессбара

#c_sharp


В предыдущем вопросе, C# Не отображаются проценты при загрузке файла с FTP , мне
подсказали данный код. Он работает, однако, я не могу использовать мой прогресс бар.
Как я понял, webClient.DownloadProgressChanged выполняется при каждом обновлении, то
есть очень быстро и с рандомной частотой. Однако, бывают случаи, когда скрипт еще не
успел отработать и по верх него накладывается еще один. Таким образом у меня срывает
прогресс бар и появляются лишние символы, которых там быть не должно.
Сам вопрос: как мне либо вывести переменную percent выше, в метод Main (что бы оттуда
был доступ к ней), либо как мне сделать так, что бы код, находящийся в webClient.DownloadProgressChanged
выполнялся не при каждом обновлении скачиваемого файла, а раз, допустим, в 1 секунду?

static void Main()
{
var uriString = @"ftp://user:password@server/Awersome.file";
long totalBytes;
var request = (FtpWebRequest)WebRequest.Create(uriString);
request.Method = WebRequestMethods.Ftp.GetFileSize;
using (var response = request.GetResponse())
{
totalBytes = response.ContentLength;
}

var webClient = new WebClient();
webClient.DownloadProgressChanged += (s, e) =>
{
int percent = (e.BytesReceived * 100 / totalBytes);
//другой код
};
webClient.DownloadFileCompleted += (s, e) => { };
webClient.DownloadFileAsync(new Uri(uriString), @"D:/1.bin");
}

    


Ответы

Ответ 1



int previousPercent = 0; webClient.DownloadProgressChanged += (s, e) => { int percent = (e.BytesReceived * 100 / totalBytes); if (percent > previousPercent) { //другой код previousPercent = percent; } };

Ответ 2



Вот ещё пример с Reactive Extensions. (Они особенно хороши, когда нужно получить контроль над потоками данных, которыми кто-то «бросается» в вас неудобным образом.) Самое сложное в нём — сконвертировать event в IObservable. async Task DownloadWithConsoleOutput(Uri uri, string savePath) { using (var wc = new WebClient()) { // все сообщения о прогрессе var allEvents = Observable.FromEventPattern( h => wc.DownloadProgressChanged += h, h => wc.DownloadProgressChanged -= h) .Select(p => p.EventArgs); var debouncedEvents = allEvents.Sample(TimeSpan.FromSeconds(1)) // не чаще раза в .DistinctUntilChanged(); // секунду и без повторов // для UI-программ скорее всего понадобится ещё .ObserveOnDispatcher(); // подписываемся на последовательность using (debouncedEvents.Subscribe(args => Console.WriteLine( $"Received: {args.BytesReceived} bytes, {args.ProgressPercentage}%"))) { // запускаем загрузку и дожидаемся окончания await wc.DownloadFileTaskAsync(uri, path); } Console.WriteLine("Download finished"); } }

Комментариев нет:

Отправить комментарий