ProgressBar при сканировании жесткого диска - PullRequest
5 голосов
/ 27 января 2009

Итак, я делаю простое сканирование, чтобы получить список всех папок на жестком диске (c: \ windows и c: \ windows \ system32 считаются отдельными записями). Если бы я хотел предоставить индикатор выполнения для этой 1-2-минутной задачи, как бы я это сделал? То есть я знаю, как сделать прогрессбар, но не уверен, как определить, сколько работы для него сделано.

Редактировать: обратите внимание, что предварительное сканирование НЕ является решением, так как это сканирование только получает список папок, а предварительное сканирование займет столько же времени.

Пример кода ниже. Чистый запуск в моей системе занимает менее 2 минут, а второй раз - менее 10 секунд из-за кэширования доступа к диску. Я создал варианты, основанные на стеке, а не на рекурсии.

Один механизм, который я обнаружил, который, вероятно, не на 100% надежен, но намного быстрее, чем мое сканирование, заключается в передаче «dir / s / ab / b» в мою программу и подсчете случаев новой строки. Dir совершает какое-то волшебство, которое намного лучше сканирует мой HD, чем моя программа, но я не знаю, что это за волшебство.

class Program
{
    static void recurse(string pos)
    {
        DirectoryInfo f = new DirectoryInfo(pos);
        try
        {
            foreach (DirectoryInfo x in f.GetDirectories("*"))
            {
                recurse(x.FullName);
            }
        } catch (Exception) {}
    }
    static void Main(string[] args)
    {
        recurse("c:\\");
    }
}

Ответы [ 7 ]

8 голосов
/ 27 января 2009

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

Например, вы создаете функцию, которая подразделяет индикатор выполнения в зависимости от количества подкаталогов в текущем каталоге. Так что, если ваш корневой каталог имеет 10 подкаталогов, выделите 10% индикатора выполнения для каждого из этих каталогов. Затем войдите в первый подкаталог и сосчитайте его подкаталоги. Если он имеет 5, выделите 20% первых 10% индикатора выполнения для каждого из них (2% от общего индикатора выполнения). Продолжайте так до тех пор, пока не дойдете до каталога без подкаталогов, выполните там свою обработку и увеличьте индикатор выполнения на любую дробную величину, которую он представляет.

Каждый% на индикаторе выполнения не будет представлять собой тот же объем работы, выполненной алгоритмом, но, учитывая ваши ограничения, я сомневаюсь, что вы можете сделать намного лучше.

2 голосов
/ 27 января 2009

Просто не используйте его. Попробуйте что-нибудь более подходящее, например, анимацию вращения или панель стиля Киттса: http://en.wikipedia.org/wiki/KITT.

1 голос
/ 28 января 2009

Я попытался получить стандартный вывод "dir/ad/b/s c:/" и подсчитать количество строк. Это довольно быстро. Он достаточно надежен для использования в прогресс-баре, но недостаточно надежен для использования в качестве списка каталогов.

1 голос
/ 27 января 2009

Вы можете сделать это несколькими способами ... простой процесс, который может быть не на 100% точным.

Прежде чем начать, получите количество файлов, затем используйте его для расчета процента выполнения, после обработки X-файлов обновите ход выполнения. Конечно, есть стоимость поиска. Может быть, просто получить количество корневых каталогов, и по мере продвижения обновлять прогресс.

Другой вариант может заключаться в том, чтобы просто записать количество деталей «последнего запуска» и использовать их для расчета процента, опять-таки, не обязательно с точностью до 100%, но как вариант.

Полагаю, несколько других вещей, которые приходят на ум, это просто показать пользователю диалог «в процессе» и даже не пытаться получить процент. В противном случае, возможно, просто покажите текущий рабочий каталог, показывая, что вы делаете успехи.

0 голосов
/ 28 декабря 2010

Я использовал метод Catchwa. Я установил диапазон прогресса на 14000, потому что операционные системы в моей системе имеют столько же директорий. Когда я нашел пустой каталог, я добавил дробную взвешенную сумму в индикатор выполнения. Количество основано на глубине и нормализовано с диапазоном. При каждом обходе поддерева вы в конечном итоге получаете пустой каталог, а вес всех пустых поддерев в каталоге составляет вес каталога, но разбитый на куски. Когда я нашел непустую директорию, я сохранил количество субдиректорий на карте. Я получил, используя Qt:

emit findProgressBar_setRange(14000); ... if (dir.size()) { m_dirsAtDepth[++m_depth] = dir.size(); } else { qreal product = 1.00; for (int i = 1; i <= m_depth; ++i) { product *= m_dirsAtDepth[i]; } int x = qRound((1.00 / product) * 14000); emit findProgressBar_addValue(x); }

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

0 голосов
/ 27 января 2009

Вы можете создать индикатор выполнения с инкрементными свойствами Maximum & Value. Если для свойства «Максимум» изначально установлено значение 100, в событии «Тик таймера» увеличьте, например, значение «Максимум и значение» на 1, чтобы значения, перечисленные ниже ...

         Maximum    Value 
Tick1:    101          1   - 1% 
Tick2:    102          2   - 2%
Tick3:    103          3   - 3% 
TickN:    100+n        n 
Finish    100+n      100+n - 100%  --> force to fill the progress bar

Вы можете поэкспериментировать с вашим начальным максимальным значением, чтобы индикатор выполнения стал более плавным.

0 голосов
/ 27 января 2009

Если вы не можете просмотреть структуру каталогов, поскольку это займет столько времени, сколько потребуется для выполнения задачи, лучшее, что вы можете сделать, - это угадать, сколько папок существует. Шутки в сторону.

Возможно, вы можете использовать алгоритм, основанный на прошлой истории (например, в последний раз, когда я делал это, было всего 150 каталогов, когда было 10 каталогов верхнего уровня, поэтому хорошее предположение было бы в 15 раз больше текущего числа каталоги уровней).

Другой способ сообщить пользователю, что что-то займет некоторое время (не зная точно, сколько времени), это использовать таймер обратного отсчета. Даже если вы догадались, что что-то займет больше времени, чем на самом деле (скажем, 5 минут, когда это действительно 3-минутное задание), по крайней мере, пользователь примерно знает, сколько времени это займет. И они будут счастливее, когда он закончится быстрее, чем им было сказано. Единственный облом, конечно, в том, что если вы ошибаетесь с другой стороны, то есть если что-то занимает больше времени, чем вы думали. Затем они сидят и ждут, когда что-то закончится, что (по их мнению) должно было уже закончиться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...