2010-03-24 27 views
17

L'applicazione che sto scrivendo esegue un algoritmo di lunghezza che di solito richiede alcuni minuti per terminare. Durante questo periodo mi piacerebbe mostrare all'utente una barra di avanzamento che indica quanto dell'algoritmo è fatto nel modo più preciso possibile.Modelli di progettazione Progress Bar?

L'algoritmo è diviso in più fasi, ognuna con il proprio tempismo tipico. Per esempio-

  • inizializzazione (500 milli-secondi)
  • ingressi di lettura (5 sec)
  • passaggio 1 (30 sec)
  • passo 2 (3 minuti)
  • scrittura delle uscite (7 sec)
  • spegnimento (10 milli-secondi)

Ogni passo può riferire i suoi progressi abbastanza facilmente impostando il r prima che funzioni, dì [da 0 a 150] e poi riferisci il valore completato nel suo ciclo principale.

Quello che attualmente ho impostato è uno schema di monitor di progresso nidificati che formano una sorta di albero implicito di segnalazione dei progressi.

Tutti i monitor progresso ereditano da un'interfaccia IProgressMonitor:

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

La radice dell'albero è la ProgressMonitor che è collegato all'interfaccia GUI attuale:

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

Qualsiasi altro nodo nell'albero sono i monitor che prendono il controllo di un pezzo del progresso genitore:

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

A SubProgressMonitor prende il controllo dell'intervallo [parentFrom, parentFrom+parentLength] della madre.

Con questo schema sono in grado di dividere in modo statico l'avanzamento del livello superiore in base alla porzione relativa prevista di ciascun passaggio nel tempo globale. Ogni passo può essere ulteriormente suddiviso in pezzi ecc '

Lo svantaggio principale di questo è che la divisione è statica e diventa doloroso apportare modifiche in base alle variabili rilevate in fase di esecuzione.

Quindi la domanda: esistono modelli di progettazione noti per il monitoraggio dell'avanzamento che risolvono questo problema?

risposta

1

Questo è un problema difficile, anche in un precedente progetto abbiamo avuto difficoltà.

Il meglio che ho potuto ricavare è quello di raccogliere le statistiche di quanto tempo ciascuna fase effettivamente impiega nella vita reale e regolare di conseguenza le lunghezze dell'intervallo relative.

Non abbiamo implementato in quel progetto anche se (almeno finché ero lì), quindi questo è solo un'idea teorica :-)

4

Pietro è stato l'approccio che ho preso su un progetto di grandi dimensioni; durante il nostro lancio pilota e iniziale, ciascuno dei nostri migliaia di dispositivi mobili stava inviando i tempi e i dati di utilizzo, e abbiamo utilizzato la media, la mediana e le deviazioni standard del tempo impiegato per ottimizzare la configurazione dei nostri compiti (quando il è stato possibile eseguire l'attività, per quanto tempo è stato possibile eseguire, quali valori sono stati utilizzati nella barra di avanzamento, ecc.). Poiché la nostra soluzione è stata costruita un po 'come la tua ma guidata dai valori forniti in un file di configurazione XML, abbiamo pensato di costruirlo come un sistema automatico (ad esempio, il server controllerebbe questi valori su un intervallo, notando che alcune attività richiedevano più tempo negli ultimi giorni di quello che erano soliti aggiornare il file di configurazione per riprogrammarli o allungarli), ma pensavo che non valesse la pena solo per evitare una rapida revisione umana ogni poche settimane.

Poiché non conosco una soluzione tecnica al problema, penso che ciò che mostri all'utente (e quanto tempo spendi per lo sviluppo di una soluzione) dovrebbe essere basato su problemi funzionali: chi lo sta utilizzando? quanto devono essere accurate le informazioni? È un processo interattivo durante il quale non possono fare altro, o possono lasciarlo correre in background e tornare ad esso? Il processo di lavoro durante il quale la tua funzione di lunga durata si verifica in un momento critico o mission-critical?

Mi dispiace di non poterti dare la risposta che stai cercando, ma forse pensare a quello che stai cercando di ottenere a colpi larghi perde una buona idea. =)

5

Un approccio molto interessante è la percezione dell'utente.

Chris Harrison pubblicato un documento su come utente percepisce il passare tempo a seconda dei progressi riferiti dalla barra di avanzamento (anche se la durata effettiva era ovviamente identica in tutti gli esperimenti)

noti che la formula di visualizzazione preferito è (x + (1-x)/2) dove x è la realizzazione effettiva una scala 0 a 1 :)

Pertanto, suggerirei:

  • raccogliere alcune statistiche sulla percentuale di tempo che una determinata attività richiede
  • misurare l'inizializzazione e utilizzarla per ridimensionare i progressi sulla barra di avanzamento, essendo pessimista (preparare un buffer del 10-15% per esempio)
  • poco prima dell'ultima compito (o pochi ultimi compiti, purché abbiano una durata deterministica)

lo so, non è preciso, ma se gli utenti pensano è più veloce che mi accontenterò!

0

Si potrebbe prendere in considerazione la sostituzione della barra di avanzamento, con un cerchio di avanzamento. Se l'attività ha N passaggi, quindi creare N zeppe nella torta e riempire ciascun cuneo come una barra di avanzamento, mentre viene eseguito quel passaggio.

Come passaggio aggiuntivo, è possibile che venga visualizzato del testo per ogni passaggio, in modo che abbiano qualcosa da leggere mentre il passaggio procede.

2

Costruire un AggregateProgressMonitor che calcola automaticamente le divisioni di avanzamento del bambino in base alle informazioni riportate dai monitor di avanzamento figlio.Il monitor dei progressi del bambino dovrebbe almeno informare il genitore del tempo di esecuzione "previsto". I tempi di esecuzione stimati del monitor figlio possono quindi essere aggiornati dalle rispettive operazioni in base ai parametri di runtime e la segnalazione generale dell'avanzamento verrà regolata di conseguenza e automaticamente.

qualcosa di simile ...

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

È anche possibile utilizzare il tempo osservato del primo passo per rimappare i successivi giornalisti progresso per essere più precisi.

Avrete bisogno di tenere una mappa ordinata di qualche tipo in AggregateProgressMonitor per essere in grado di tracciare e calcolare tutte le informazioni dai bambini.

Una volta completato, è possibile estendere AggregateProgressMonitor (sovrascrivendo i metodi di IProgressMonitor) per visualizzare l'avanzamento all'utente.

Problemi correlati