web-dev-qa-db-fra.com

Mettre à jour l'étiquette pendant le traitement dans Windows Forms

Quelle est la meilleure façon de mettre à jour une étiquette sur une application Windows Forms pendant le traitement?

J'ai une boucle qui effectue un certain traitement des fichiers sur le système de l'utilisateur lorsque l'utilisateur clique sur un bouton.

foreach (System.IO.FileInfo f in dir.GetFiles("*.txt"))
{
   // Do processing
   // Show progress bar
   // Update Label on Form, "f.Name is done processing, now processing..."
}

Quel serait un exemple de code?

Comment s'appelle-t-on exactement? Est-ce du filetage ou des délégués?

31
Picflight

Une solution rapide pour vous serait:

Label1.Text = f.Name + " is done processing, now processing...";
Label1.Refresh();

Vous voulez vraiment éviter DoEvents, sinon vous aurez des problèmes si votre utilisateur appuie à plusieurs reprises sur les boutons de votre formulaire.

60
Patrick McDonald

Vous devrez obtenir vos données d'un fil à l'autre. Cela peut se faire de deux manières ...

Tout d'abord, votre thread "d'arrière-plan" pourrait mettre à jour une sorte de variable de chaîne "CurrentStatus" qu'il modifie au fur et à mesure. Vous pouvez ensuite mettre une minuterie sur votre formulaire qui saisirait alors la variable CurrentStatus et mettrait à jour l'étiquette avec elle.

Deuxièmement, vous pouvez simplement appeler l'opération du thread d'arrière-plan au thread d'interface utilisateur avec un délégué à l'aide de la propriété InvokeRequired du contrôle d'étiquette. Donc par exemple ...

private delegate void UpdateStatusDelegate(string status);
private void UpdateStatus(string status)
{
    if (this.label1.InvokeRequired)
    {
        this.Invoke(new UpdateStatusDelegate(this.UpdateStatus), new object[] { status });
        return;
    }

    this.label1.Text = status;
}

Vous pouvez appeler cette méthode UpdateStatus () à partir de n'importe quel thread (interface utilisateur ou arrière-plan), et il détectera s'il doit ou non appeler l'opération sur le thread d'interface utilisateur principal (et si c'est le cas, le fait).

Pour configurer réellement le fil, vous pouvez le faire comme ceci:

    private void StartProcessing()
    {
        System.Threading.Thread procThread = new System.Threading.Thread(this.Process);

        procThread.Start();
    }

    private void Process() // This is the actual method of the thread
    {
        foreach (System.IO.FileInfo f in dir.GetFiles("*.txt"))
        {
            // Do processing
            // Show progress bar
            // Update Label on Form, "f.Name is done processing, now processing..."
            UpdateStatus("Processing " + f.Name + "...");                
        }
    }

Ensuite, lorsque l'utilisateur clique sur le bouton "GO", vous appellerez simplement StartProcessing ().

13
Brandon

Vous devriez faire cela sur un autre thread, puis mettre à jour votre thread d'interface utilisateur à partir de ce thread. Vous bloquez le traitement ultérieur en effectuant ce travail sur le thread d'interface utilisateur.

Si vous ne pouvez pas déplacer ce code vers le thread d'interface utilisateur, vous pouvez toujours appeler Application.DoEvents , mais je fortement vous suggère d'explorer d'abord ces options:

13
casperOne

Si votre traitement est long, faites-le dans un thread d'arrière-plan.

http://msdn.Microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

1
devSpeed

Je recommande également d'utiliser:

Application.DoEvents();

Traite tous les messages Windows actuellement dans la file d'attente de messages.

0
Dominique Mathieu