Come posso visualizzare i progressi durante un ciclo occupato?

Sto lavorando in C # e WPF, molto nuovo per entrambi.

Ho un ciclo che legge un sacco di dati da una fonte esterna. Il processo dura circa 20 secondi e voglio mostrare i progressi all’utente. Non ho bisogno di barre di progresso elaborate, quindi ho scelto di tracciare i miei progressi in un’etichetta che dirà “Passo 1/1000”, quindi passare a “Passaggio 2/1000” ecc.

Il mio codice è simile a questo:

// "count" is the number of steps in the loop, // I receive it in previous code String countLabel = "/"+count.ToString(); for (i = 0; i < count; i++) { ... do analysis ... labelProgress.Content = "Step "+i.ToString()+countLabel } 

Tuttavia, durante l’analisi, lo schermo è “bloccato” e il progresso non viene mostrato come avanzamento. Capisco questo comportamento dal mio passato in C ++, dove probabilmente avrei un thread separato che mostra una barra di avanzamento che riceve notifiche dal ciclo, o qualche forma di ridisegno / aggiornamento, o costringe la finestra / app a elaborare la sua coda di messaggi.

Qual è il modo giusto per farlo in C #? Non sono legato all’etichetta, quindi se c’è una semplice schermata popup di progressione che potrei usare al posto di questa etichetta sarebbe anche grandiosa …

Grazie

Spostare il lavoro su un BackgroundWorker e utilizzare il metodo ReportProgress .

 for (i = 0; i < count; i++) { ... do analysis ... worker.ReportProgress((100 * i) / count); } private void MyWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { taskProgressBar.Value = Math.Min(e.ProgressPercentage, 100); } 
  //Create a Delegate to update your status button delegate void StringParameterDelegate(string value); String countLabel = "/" + count.ToString(); //When your button is clicked to process the loops, start a thread for process the loops public void StartProcessingButtonClick(object sender, EventArgs e) { Thread queryRunningThread = new Thread(new ThreadStart(ProcessLoop)); queryRunningThread.Name = "ProcessLoop"; queryRunningThread.IsBackground = true; queryRunningThread.Start(); } private void ProcessLoop() { for (i = 0; i < count; i++) { ... do analysis ... UpdateProgressLabel("Step "+i.ToString()+countLabel); } } void UpdateProgressLabel(string value) { if (InvokeRequired) { // We're not in the UI thread, so we need to call BeginInvoke BeginInvoke(new StringParameterDelegate(UpdateProgressLabel), new object[] { value }); return; } // Must be on the UI thread if we've got this far labelProgress.Content = value; } 

L’interfaccia utente non viene aggiornata a causa del fatto che il thread corrente ha una priorità più alta rispetto al thread dell’interfaccia utente che alla fine imposterà l’etichetta;). Quindi, fino a quando il tuo thread non avrà completato i tuoi contenuti, aggiornerà l’etichetta alla fine.

Fortunatamente per noi, esiste una proprietà Dispatcher su ogni controllo WPF che ti consente di avviare una nuova discussione con un’altra priorità.

 labelProgress.Dispatcher.Invoke(DispatcherPriority.Background, () => labelProgress.Content = string.Format("Step {0}{1}", i, countLabel)); 

Questo accende un thread in background e dovrebbe portare a termine il lavoro! Puoi anche provare altre opzioni di DispatcherPriority

PS Mi sono anche preso la libertà di aggiungere un metodo anonimo e di aggiustare la stringa in qualche modo .. spero non ti dispiaccia ..