10 votes

Comment afficher la progression pendant une boucle occupée ?

J'ai une boucle qui lit beaucoup de données à partir d'une source externe. Le processus prend environ 20 secondes, et je veux montrer la progression à l'utilisateur. Je n'ai pas besoin de barres de progression fantaisistes, j'ai donc choisi de représenter la progression dans une étiquette qui dira "Step 1/1000", puis passera à "Step 2/1000", etc.

Mon code ressemble à quelque chose comme ceci :

// "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
}

Cependant, au cours de cette analyse, l'écran reste "bloqué" et la progression n'est pas indiquée. Je comprends ce comportement grâce à mon passé en C++, où j'aurais probablement un thread séparé montrant une barre de progression recevant des notifications de la boucle, ou une certaine forme de repeindre/rafraîchir, ou forçant la fenêtre/application à traiter sa file d'attente de messages.

Quelle est la bonne façon de le faire en C# ? Je ne suis pas lié à l'étiquette, donc s'il y a un simple écran popup de barre de progression que je pourrais utiliser à la place de cette étiquette, ce serait également génial...

Merci

13voto

user7116 Points 39829

Déplacez le travail vers un Travailleur d'arrière-plan et utiliser le ReportProgress méthode.

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

3voto

German Points 11
    //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;
    }

2voto

Arcturus Points 14366

L'interface utilisateur n'est pas mise à jour parce que votre thread actuel a une priorité plus élevée que le thread de l'interface utilisateur qui, en fin de compte, définira l'étiquette ;). Ainsi, tant que votre thread n'a pas terminé son travail, il mettra à jour votre étiquette à la fin.

Heureusement pour nous, il existe une propriété Dispatcher sur chaque contrôle WPF qui vous permet de lancer un nouveau fil avec une autre priorité

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

Cela allume un fil en arrière-plan et ferait l'affaire ! Vous pouvez également essayer d'autres Priorité du répartiteur options

PS J'ai également pris la liberté d'ajouter une méthode anonyme et de corriger quelque peu votre analyse des chaînes de caractères j'espère que cela ne vous dérange pas .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X