Прогресс Бар шаблоны дизайна? - PullRequest
18 голосов
/ 24 марта 2010

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

Алгоритм разделен на несколько этапов, каждый из которых имеет свою собственную типичную синхронизацию. Например -

  • инициализация (500 миллисекунд)
  • чтение входов (5 секунд)
  • шаг 1 (30 сек)
  • шаг 2 (3 минуты)
  • запись выходных данных (7 секунд)
  • выключение (10 миллисекунд)

Каждый шаг может довольно легко сообщать о своем прогрессе, устанавливая диапазон, над которым он работает, скажем, [от 0 до 150], а затем сообщая о завершенном значении в своем основном цикле.

То, что я сейчас настроил, - это схема вложенных мониторов прогресса, которые образуют своего рода неявное дерево отчетов о прогрессе.

Все мониторы прогресса наследуются от интерфейса IProgressMonitor:

class IProgressMonitor
{
public:
  void setRange(int from, int to) = 0;
  void setValue(int v) = 0;
};

Корнем дерева является ProgressMonitor, который подключен к реальному интерфейсу GUI:

class GUIBarProgressMonitor : public IProgressMonitor
{
   GUIBarProgressMonitor(ProgressBarWidget *);
};

Любой другой узел в дереве - это мониторы, которые контролируют часть родительского прогресса:

class SubProgressMonitor : public IProgressMonitor
{
  SubProgressMonitor(IProgressMonitor *parent, int parentFrom, int parentLength)
  ...
};

A SubProgressMonitor контролирует диапазон [parentFrom, parentFrom+parentLength] своего родителя.

С помощью этой схемы я могу статически разделить прогресс на высшем уровне в соответствии с ожидаемой относительной частью каждого шага в глобальном времени. Затем каждый шаг можно разделить на части и т. Д.

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

Итак, вопрос: существуют ли какие-либо известные шаблоны проектирования для мониторинга прогресса, которые решают эту проблему?

Ответы [ 5 ]

5 голосов
/ 29 марта 2010

Очень интересный подход - восприятие пользователя.

Крис Харрисон опубликовал статью о том, как пользователь воспринимает время, проходящее в зависимости от прогресса, отображаемого индикатором выполнения (хотя фактическая продолжительность была, очевидно, идентична во всех экспериментах)

Обратите внимание, что предпочтительной формулой отображения является (x + (1-x) / 2) 8 , где x - фактический прогресс по шкале от 0 до 1:)

Поэтому я бы предложил:

  • собрать некоторую статистику о проценте времени, которое занимает выполнение задачи
  • измерить инициализацию и использовать ее для масштабирования вашего прогресса на индикаторе выполнения, будучи пессимистичным (например, подготовить буфер на 10-15%)
  • непосредственно перед последним заданием (или несколькими последними заданиями, если они имеют детерминированную продолжительность), изо всех сил, чтобы завершить индикатор выполнения во времени (с прогрессивным ускорением)

Я знаю, это не точно, но если пользователи думают, что это быстрее, я согласен на это!

4 голосов
/ 24 марта 2010

Петер был подходом, который я выбрал для большого проекта; Во время нашего пилотного и начального развертывания каждое из наших тысяч мобильных устройств отправляло данные о времени и использовании, и мы использовали среднее, медианное и стандартное отклонения времени, необходимого для точной настройки конфигурации наших задач (когда задание было разрешено запускать, как долго было разрешено его выполнение, какие значения использовались при отображении индикатора выполнения и т. д.). Поскольку наше решение было немного похоже на ваше, но основывалось на значениях, предоставленных в XML-файле конфигурации, мы подумали о том, чтобы создать его как автоматизированную систему (например, сервер будет проверять эти значения через некоторый интервал, заметив, что некоторые задачи в последнее время занимали больше времени) дней, чем раньше, и обновляли конфигурационный файл, чтобы перепланировать или удлинить их), но полагал, что это не стоит хлопот только для того, чтобы предотвратить быструю проверку человеком каждые несколько недель.

Поскольку я не знаю о техническом решении вашей проблемы, я думаю, что то, что вы показываете пользователю (и сколько времени вы тратите на разработку решения), должно основываться на функциональных соображениях: кто это использует? Насколько точной должна быть информация? Является ли это интерактивным процессом, во время которого они не могут выполнять никакой другой работы, или они могут запустить его в фоновом режиме и вернуться к нему? Является ли рабочий процесс, в течение которого ваша долгосрочная функция, чувствительным ко времени или критичным?

Мне жаль, что я не могу дать вам ответ, который вы ищете, но, возможно, размышления о том, чего вы пытаетесь добиться широкими ударами, сбивают хорошую идею. =)

2 голосов
/ 19 мая 2010

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

Как то так ...

class IAggregateProgressMonitor : public IProgressMonitor
{
   void setChildValue(IProgressMonitor *, int v);
   void setChildEstimatedTime(IProgressMonitor *, int v);
}

class AggregateProgressMonitor : public IAggregateProgressMonitor 
{
   void setChildValue(IProgressMonitor * child, int v)
   {
      int aggregateValue = mapChildValueToAggregateValue(child, v);
      setValue(aggregateValue);
   }

   void setChildEstimatedTime(IProgressMonitor * child, ulong ms)
   {
      children[child]->estimatedTime = ms;
      updateChildProgressRatios();
   }
}

class SubProgressMonitor : public IProgressMonitor
{
  SubProgressMonitor(IAggregateProgressMonitor *parent, int parentFrom, 
                     int parentLength) ... ;
  void setValue(int v)
  {
     parent->setChildValue(this, v);
  }

  void setEstimatedRunningTime(ulong ms)
  {
    parent->setChildEstimatedTime(this, ms);
  } 
};

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

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

После завершения вы можете расширить AggregateProgressMonitor (переопределяя методы IProgressMonitor) для отображения прогресса пользователю.

1 голос
/ 24 марта 2010

Это сложная проблема, с которой мы тоже боролись в предыдущем проекте.

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

Хотя мы не реализовали его в этом проекте (по крайней мере, пока я там был), так что это всего лишь теоретическая идея: -)

0 голосов
/ 29 марта 2010

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

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

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