Una soluzione semplice qui se applicabile (non consolida il progresso per le operazioni asincrone che funzionano indipendentemente l'una dall'altra, sebbene tu possa ancora usare questo metodo per quelli per calcolare percentuali al loro interno) e puoi anticipare il numero di fasi in anticipo in un contesto esterno (anche se non è possibile prevedere quanto lavoro è richiesto in ogni fase prima di invocarli), il che porta a una barra di progresso * abbastanza liscia * è la seguente:
- It might not increment in progress in a perfectly consistent way across phases, but should still keep moving forward without going past 100%.
Pseudocodice:
funcprogress(n):ifstack_size<n:return(steps[n]/total[n])+(1/total[n])*progress(n+1);else:return0;
Speriamocheloschemaeilcodicetidianogiàun'ideadell'implementazioneusandoun"stack di progresso" e qualche semplice aritmetica per calcolare il progresso fino ad ora, e puoi annidarli quanto vuoi (fasi che si dividono in sotto -le fasi che si suddividono in fasi sub-sub) senza preoccuparsi di traboccare la barra e superare il 100% o qualcosa del genere.
Tutto ciò che devi fare è in un contesto esterno, anticipare quante fasi hai (3 in questo caso), nel qual caso incrementerai il progresso con incrementi del 33,3% per fase. Ma quando chiamiamo la funzione per phase 1
, potremmo scoprire che questa prima fase richiede 100 sottomulti da completare dopo aver chiamato la funzione, a quel punto il 33,3% di progresso, per parlare, poi viene incrementato di 100 passi per anticipo dallo 0% al 33% e così via. Il codice client potrebbe assumere questa forma:
function some_outer_operation(progress)
{
// begin performing a total of 3 units/steps of work
progress.begin(3)
phase1()
progress.step()
phase2()
progress.step()
phase3()
progress.step()
}
function phase1()
{
// begin performing a total of 100 units/steps of work
progress.begin(100)
for j in range(1, 100):
{
some_work()
progress.step()
}
}
... qualcosa di questo tipo e chiamate ricorsive a begin
"suddividono" il pezzo esterno del progresso da incrementare. Quando il numero di passaggi raggiunge il totale per una fase o sottofase o sottofase secondaria o qualsiasi altra cosa, puoi uscire dalla pila. Ciò richiede comunque la specificazione dei numeri ma non richiede necessariamente di avere così tante informazioni in anticipo su tutti i passaggi coinvolti in tutte queste chiamate di funzioni annidate, solo il numero di fasi / fasi che coinvolgono in una particolare funzione e non le "sotto-funzioni" ".
Stranamente semplice come questa soluzione, lo faccio notare perché ho visto soluzioni "piatte" molto contorte (senza questo tipo di stack per operazioni annidate) in cui gli sviluppatori dovevano anticipare il numero totale di passaggi per tutto in anticipo e che a volte richiede il controllo a raggi x dell'implementazione delle funzioni chiamate e dei richiami di funzione delle funzioni chiamate e così via. In questo modo si evita che una grande quantità di conoscenze sia richiesta in anticipo e richiede solo che una funzione abbia bisogno di sapere quanti passaggi si esegue, non tutte le funzioni più in profondità nello stack di chiamate.
Ovviamente potrebbe non essere perfettamente coerente nel modo in cui aumenta (es .: potrebbe richiedere 1 secondo per passare dallo 0 al 33% e 3 secondi per passare dal 33% al 66%), ma può rimanere molto fluido e reattivo e in continua evoluzione in corso, a patto che i passaggi siano abbastanza dettagliati nei tuoi "leaf" call (la tua fase o sottofase o sub-sub-sub-sub-fase o quant'altro).
I even started thinking about recording the time taken, and using these numbers to make dynamic estimations during the next run - but that's overkill, I think.
Se si arriva a questo, vorrei solo dare il consiglio di mostrare solo qualcosa in corso senza una barra di avanzamento, di per sé. Si sta facendo così di fantasia per così poco in cambio se non è possibile anticipare nemmeno il numero di fasi coinvolte in anticipo (es: un euristico che richiede N
passa sopra i dati dove N
non può essere anticipato in anticipo prima dell'algoritmo in corso di completamento).
Le barre di avanzamento spesse che non aumentano molto agevolmente, inoltre, non si sentono così male se ti piace qualcosa di animazione accanto e puoi annullare l'operazione all'istante, ad esempio. Comunica abbastanza che l'applicazione non si è appena arrestata e non ha più risposto. Quindi non dovresti nemmeno preoccuparti di "suddividere" la barra di avanzamento per i sottomulti delle fasi e solo invece assicurarti che l'interfaccia utente continui ad aggiornarsi e mostri qualcosa che va avanti ad un frame rate ragionevole e risponde abbastanza velocemente se l'utente può abortire anche se la barra non si muove a un ritmo così regolare e rapido.