2012-10-25 5 views
5

Ho un semplice modulo con 2 barre di avanzamento e 1 backgroundworker su di esso. Ho 2 cicli (uno dentro l'altro) e vorrei segnalare l'avanzamento di ogni ciclo una volta incrementato. Ecco il codice che ho:Solo 1 di 2 barre di avanzamento viene aggiornato in BackgroundWorker

private void buttonStart_Click(object sender, EventArgs e) 
{ 
    workerCustomers.RunWorkerAsync(); 
} 

private void workerCustomers_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    progressBar1.Value = e.ProgressPercentage; 
    progressBar2.Value = (int)e.UserState; 
} 

private void workerCustomers_DoWork(object sender, DoWorkEventArgs e) 
{ 
    for (int customer = 0; customer < 50; customer++) 
    { 
     int customerPercentage = ++customer * 100/50; 
     workerCustomers.ReportProgress(customerPercentage, 0); 

     for (int location = 0; location < 500; location++) 
     { 
      int locationPercentage = ++location * 100/500; 
      workerCustomers.ReportProgress(customerPercentage, locationPercentage); 
     } 

     workerCustomers.ReportProgress(customerPercentage, 0); 
    } 
} 

Quando il programma viene eseguito, progressBar1 viene aggiornato più che bene, ma progressbar2 non si muove mai. Se lo eseguo attraverso il debugger, posso vedere il valore di progressbar2 che viene modificato, non c'è alcun cambiamento graficamente. Qualche idea?

+0

Il valore massimo della barra di avanzamento è impostato correttamente? –

+0

@lc., Sì, per impostazione predefinita, è impostato su 100 ma l'ho modificato per far corrispondere il totale del contatore del ciclo 2 in totale di 500. – Robert

+1

Un ciclo di 500 andrà molto velocemente. Potrebbe non sembrare un aggiornamento. Prova ad aggiungere Thread.Sleep() al ciclo interno e verifica se in realtà sta accadendo troppo rapidamente per poterlo vedere. –

risposta

5

Sì, la seconda barra di avanzamento non verrà aggiornata se sul desktop è abilitato Aero. Che fornisce la barra di avanzamento animata, quella che è verde per impostazione predefinita con la nota di evidenziazione in viaggio.

Questa barra di avanzamento stile è speciale, interpola i valori intermedi e guarda sempre liscia, anche se si assegna valori corso alla proprietà Value. In altre parole, puoi assegnare 10, 20, 30, eccetera ma la barra non salta. Aumenta dolcemente la lunghezza della barra.

Questo ha effetti collaterali. Per far funzionare questa animazione, la barra di avanzamento deve lag. In altre parole, mostra sempre un valore che è dietro a il valore programmato. E un po 'di tempo deve passare per aumentare dolcemente la lunghezza della barra al valore programmato.

più Un dettaglio è necessario sapere: questa animazione non non accada quando si diminuire la proprietà Value, che salta subito alla lunghezza della barra.

Quindi il problema è che si sta aggiornando la proprietà Value a un tasso molto alto, molto più veloce rispetto il bar può interpolare. Non può mai recuperare. Tranne quando si riavvia a 0, che salta immediatamente la barra. Il tasso è così alto che l'animazione non può mai rendere al 1.

Potete vedere questo con l'inserimento di questa istruzione all'interno del ciclo interno:

System.Threading.Thread.Sleep(1); 

giocare con il valore dell'argomento, potrebbe essere necessario aumentare a 16 per vedere alcuna differenza. Più lo fai, più la barra lo fa per interpolazione.

Questo è, naturalmente, non è un problema reale, questo accade perché il lavoratore non sta facendo alcun lavoro reale. Non appena inizi a scrivere il vero codice che questo BGW dovrebbe fare, ridurrai anche la velocità con cui chiami ProgressChanged.

+0

grazie per questa risposta dettagliata, ho imparato molto. Qual è l'approccio migliore a questo problema? – Robert

+1

Ero esplicito a riguardo, ultimo paragrafo. –

1

Il problema sta nel fatto che il vostro ciclo interno è così stretto che gli aggiornamenti GUI postando troppo spesso per la GUI di rispondere con precisione a loro. La soluzione è aggiungere il tuo lavoro reale al ciclo interno, quindi richiede più tempo o se vuoi simulare la GUI, puoi semplicemente aggiungere un Thread.Sleep(100) per simulare il lavoro che richiede del tempo.

anche garantire che i massimi barra di avanzamento sono impostati su 100, come quello è il valore massimo si restituisce per ciascuno.

0

Il tuo problema principale deriva da un ciclo interno troppo veloce che significa che non potete effettivamente vedere i progressi in quanto gli aggiornamenti sono troppo veloci per l'ProgressBar da gestire.

tuo riga di codice:

location * 100/500 

sarà pari al 100 quando hai finito il ciclo interno, in modo da avere il valore massimo progressbar impostato su 500 non si riferisce anche a quel numero. Significa che la tua barra di avanzamento non raggiungerà mai il valore massimo.

Problemi correlati