2010-03-24 22 views
17

Aplikacja, którą piszę, wykonuje algorytm długości, który zwykle zajmuje kilka minut. W tym czasie chciałbym pokazać użytkownikowi pasek postępu, który wskazuje, jak bardzo algorytm jest wykonany tak precyzyjnie, jak to tylko możliwe.Wzorce projektowe paska postępu?

Algorytm jest podzielony na kilka etapów, każdy z własnym typowym taktowaniem. Dla instance-

  • inicjalizacji (500 milisekund)
  • wejścia odczytu (5 s)
  • etap 1, (30 s)
  • Etap 2 (3 minuty)
  • wyjścia pisania (7 s)
  • wyłączania (10 milisekund)

Każdy krok może zgłosić swoje postępy dość łatwo poprzez ustawienie R i przeprowadź jego pracę, powiedzmy [0 do 150], a następnie podaj wartość, którą ukończyła w swojej głównej pętli.

To, co obecnie skonfigurowałem, to schemat zagnieżdżonych monitorów postępu, które tworzą rodzaj niejawnego drzewa raportów postępu.

Wszystkie monitory postępu dziedziczyć z interfejsu IProgressMonitor:

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

Korzeniem drzewa jest ProgressMonitor który jest podłączony do rzeczywistego interfejsu GUI:

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

Każdy inny węzeł w drzewie to monitory, które przejmują kontrolę nad postępem nadrzędnym:

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

A SubProgressMonitor przejmuje kontrolę nad obszarem nadrzędnym w zakresie [parentFrom, parentFrom+parentLength].

Za pomocą tego schematu mogę statycznie dzielić postęp najwyższego poziomu zgodnie z oczekiwaną względną częścią każdego kroku w globalnym taktowaniu. Każdy krok można następnie podzielić na części itp. "

Główną wadą tego jest podział na statyczny i bolesne jest wprowadzanie zmian w zależności od zmiennych, które są wykrywane w czasie wykonywania.

Pytanie więc: czy istnieją jakieś znane wzorce projektowe do monitorowania postępu, które rozwiązują ten problem?

Odpowiedz

1

Jest to trudny problem, z którym mieliśmy problem także w poprzednim projekcie.

Najlepsze, co mogę wymyślić, to zebranie statystyk, jak długo każda faza rzeczywiście trwa w rzeczywistości, i odpowiednio dostosuj względne długości interwału.

Nie wdrożyliśmy go w tym projekcie, choć (przynajmniej tak długo, jak byłem tam), więc jest to tylko pomysł teoretyczny :-)

4

Piotra było podejście wziąłem na dużym projekcie; Podczas naszego pilotażowego i początkowego wdrożenia, każde z naszych tysięcy urządzeń mobilnych odesłało dane dotyczące czasu i użytkowania, a także wykorzystaliśmy średnią, medianę i odchylenia standardowe czasu potrzebnego do precyzyjnego dostrojenia konfiguracji naszych zadań (gdy zadanie zostało uruchomione, jak długo można było uruchomić, jakie wartości były używane w wyświetlaniu paska postępu itp.). Ponieważ nasze rozwiązanie zostało zbudowane trochę jak twoje, ale oparte na wartościach podanych w pliku konfiguracyjnym XML, pomyśleliśmy o zbudowaniu tego jako systemu automatycznego (np. Serwer sprawdzałby te wartości w pewnym przedziale, zauważ, że niektóre zadania trwały dłużej w ostatnich dni niż kiedyś i zaktualizować plik konfiguracyjny, aby zmienić harmonogram lub wydłużyć czas), ale uznał, że nie było to warte kłopotów tylko po to, aby zapobiec szybkiemu ludzkiemu przeglądowi co kilka tygodni.

Ponieważ nie znam technicznego rozwiązania problemu, myślę, że to, co użytkownik pokazuje użytkownikowi (i ile czasu poświęcamy na opracowanie rozwiązania) powinno opierać się na problemach funkcjonalnych: kto z niego korzysta? jak dokładne muszą być informacje? Czy jest to interaktywny proces, podczas którego nie mogą wykonywać żadnej innej pracy, czy mogą pozwolić działać w tle i wrócić do niego? Czy proces pracy, w którym twoja długo działająca funkcja, ma znaczenie czasowe lub krytyczne?

Przykro mi, że nie mogę udzielić Ci odpowiedzi, której szukasz, ale być może myślenie o tym, co próbujesz osiągnąć w szerokim uderzeniu, jest dobrym pomysłem. =)

5

Bardzo interesującym podejściem jest percepcja użytkownika.

Chris Harrison opublikowała dokument, w jaki użytkownik postrzega upływ czasu w zależności od postępu zgłoszone przez pasek postępu (choć rzeczywisty czas trwania był oczywiście identyczne we wszystkich eksperymentach)

Należy zauważyć, że preferowana formuła wyświetlacz (x + (1-x)/2) gdzie x jest rzeczywisty postęp na skali od 0 do 1 :)

Dlatego sugeruję:

  • zbierać niektóre statystyki dotyczące procentowego czasu wykonania danego zadania wynoszą
  • mierzą inicjalizację i używają jej do skalowania twoich postępów na pasku postępu, będąc pesymistycznym (przygotowując bufor na przykład 10-15%)
  • tuż przed ostatnim Zadanie (lub kilka ostatnich zadań, o ile mają deterministyczny czas trwania), przejdź do końca, aby ukończyć pasek postępu w czasie (z progresywnym przyspieszeniem).

Wiem, to nie jest dokładne, ale jeśli użytkownicy myślą Szybciej się na to zdecyduję!

0

Możesz rozważyć zastąpienie paska postępu kółkiem postępu. Jeśli zadanie ma N kroków, a następnie N klin w ciasto, i wypełnić każdy klin jak pasek postępu, jak ten krok działa.

Jako dodatkowy krok może być wyświetlany tekst dla każdego kroku, aby można było przeczytać coś w trakcie kroku.

2

Zbuduj AggregateProgressMonitor, który automatycznie oblicza podziały postępu dziecka na podstawie informacji zgłoszonych przez monitory postępu dziecka.Monitor postępu dziecka powinien przynajmniej informować rodzica o "oczekiwanym" czasie działania. Szacowane czasy działania monitorów podrzędnych można następnie aktualizować, wykonując odpowiednie operacje na podstawie parametrów środowiska wykonawczego, a ogólne raportowanie postępu zostanie odpowiednio dostosowane i automatycznie.

Coś takiego ...

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); 
    } 
}; 

Można nawet użyć obserwowany czas pierwszego etapu przemapować kolejnych reporterów postępu być bardziej dokładne.

Będziesz musiał zachować uporządkowaną mapę w AggregateProgressMonitor, aby móc śledzić i obliczać wszystkie informacje od dzieci.

Po zakończeniu można rozszerzyć AggregateProgressMonitor (przesłonięcie metod IProgressMonitor), aby wyświetlić postępy dla użytkownika.

Powiązane problemy