2010-11-05 5 views
3

Je souhaite en savoir plus sur le threading et créer une petite application de test qui modifie la couleur de fond d'une étiquette.Test de thread simple

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    //lblColor 
    public Color theLabel 
    { 
     get { return this.lblColor.BackColor; } 
     set { this.lblColor.BackColor = value; } 
    } 

    //btnStart 
    private void btnStart_Click(object sender, EventArgs e) 
    { 
     ThreadTest cColor = new ThreadTest(); 
     Thread tColor = new Thread(new ThreadStart(cColor.ChangeColor)); 

     tColor.Start(); 
    } 
} 

Et ...

public class ThreadTest 
{ 
    public void ChangeColor() 
    { 
     Form1 foo = new Form1(); 
     while (true) 
     { 
      foo.theLabel = Color.Aqua; 
      foo.theLabel = Color.Black; 
      foo.theLabel = Color.DarkKhaki; 
      foo.theLabel = Color.Green; 
     } 
    } 
} 

Le seul problème est pourquoi je ne peux pas faire ce travail de code? Je peux voir que le code dans ChangeColor s'exécute mais la couleur de l'étiquette ne change pas.

+2

C'est parce que votre fils n » asynchrone ... le formulaire réside sur le même fil que votre code de changement, et donc le formulaire n'a aucune chance de se redessiner. Je suis juste trop paresseux pour former maintenant une réponse qui explique exactement pourquoi et comment utiliser les délégués. – Bobby

+0

Comme indiqué dans ma réponse ci-dessous, le code ne fonctionne pas à cause de Form1 foo = new Form1(); dans ThreadTest.ChangeColor ... utilisez le début de thread paramétré ... toutes les suggestions concernant backgroundworker etc sont aussi de bonnes idées. –

Répondre

5

À première vue, vous construisez une nouvelle forme

Form1 foo = new Form1(); 

intérieur ThreadTest et ne jamais afficher la forme, je suppose que vous destiné à changer la couleur du formulaire sur le formulaire avec btnStart? Vous avez deux options, soit passer dans le formulaire dans un ParameterizedThreadStart ou réécrire le code pour simplement opérer sur le formulaire existant. En outre, en fonction du code écrit, vous devrez probablement utiliser Invoke pour mettre à jour l'état du formulaire, car les threads de travail ne peuvent pas mettre à jour l'interface utilisateur. Je vais modifier votre code et posté un exemple révisé si quelqu'un ne me bat pas.

Modifier

Dans ce cas, vous n'avez pas besoin Invoke ... mais voici ce que je pense que vous aviez l'intention ...

private void btnStart_Click(object sender, EventArgs e) 
{ 
    ThreadTest cColor = new ThreadTest(); 
    Thread tColor = new Thread(new ParameterizedThreadStart(cColor.ChangeColor)); 

    tColor.Start(this); 
} 

public class ThreadTest 
{ 
    public void ChangeColor(Object state) 
    { 
    Form1 foo = (Form1) state; 
    while (true) 
    { 
     foo.theLabel = Color.Aqua; 
     foo.theLabel = Color.Black; 
     foo.theLabel = Color.DarkKhaki; 
     foo.theLabel = Color.Green; 
    } 
    } 
} 

, il est également important de définir threads de travail en tant que threads d'arrière-plan, sinon, lorsque vous fermez le formulaire, le thread gardera cette application ouverte.

tColor.IsBackground = true; 

Exemple supplémentaire

Un exemple légèrement différent serait d'avoir plusieurs threads essayant de mettre à jour la même valeur et voir comment ils sont intercalés ... simple extrait pour obtenir rouler la balle.

private void btnStart_Click(object sender, EventArgs e) 
{ 
    CreateBackgroundColorSetter(Color.Aqua); 
    CreateBackgroundColorSetter(Color.Black); 
    CreateBackgroundColorSetter(Color.DarkKhaki); 
    CreateBackgroundColorSetter(Color.Green); 
} 


private void CreateBackgroundColorSetter(Color color) 
{ 
    var thread = new Thread(() => 
          { 
           while (true) 
           { 
           theLabel = color; 
           Thread.Sleep(100); 
           } 
          }); 
    thread.IsBackground = true; 

    thread.Start(); 
} 
+0

Double +1 pour les échantillons multiples. – cjk

3

vous avez 2 numéros

a) vous n'êtes pas censé mettre à jour l'interface utilisateur d'autres threads

b), même si vous avez été autorisé à le faire, vous devez indiquer l'interface utilisateur pour repeindre

ce sont des questions non triviales

Si vous êtes expérimentant avec filetage puis utilisez Debug.WriteLine pour voir ce que les fils de fond font

Si vous avez réellement besoin de mettre à jour l'interface utilisateur en arrière-plan, puis rechercher BeginInvoke et InvokeNeeded

+0

Le code s'exécute réellement si vous corrigez ThreadTest.ChangeColor pour ne pas créer un nouveau formulaire. Voir l'exemple ci-dessous. Typiquement, vous avez besoin d'une invocation (et j'ai été surpris que ce n'était pas nécessaire dans ce cas). –

1

Si vous avez vraiment besoin de faire filetage dans une application GUI, vous allez avoir besoin BackgroundWorker ou quelque chose comme ça. Comme indiqué précédemment, les autres threads ne peuvent pas mettre à jour l'interface graphique de sorte que l'exemple montré ici est un meilleur modèle pour déplacer des éléments de travail de longue durée hors de votre thread principal.

La classe BackgroundWorker vous permet d'exécuter une opération sur une procédure distincte, thread dédié. Les opérations prenant beaucoup de temps, comme les téléchargements et les transactions de base de données , peuvent provoquer l'apparition de l'interface utilisateur (UI) comme si avait cessé de répondre alors qu'ils sont en cours d'exécution. Lorsque vous voulez une interface utilisateur réactive et que vous êtes confronté à de longs délais associés à de telles opérations, la classe BackgroundWorker fournit une solution pratique.

+0

Je suis d'accord que BackgroundWorker est un meilleur moyen de gérer cette période d'application, et sera finalement nécessaire lorsque vous frapperez des exemples plus complexes, mais la raison pour laquelle le code ne s'exécute pas est le form1 foo = new Form1(); instruction dans ThreadTester.ChangeColor (voir ma réponse). –

+0

@Calgary Coder - oui, cette information était destinée à compléter les réponses existantes qui se rapportent à la cause immédiate. –

0

Si vous voulez faire des expériences avec le thread, créez simplement une application de console et allez sur google "tutorial C#" pour avoir un exemple.

En ce qui concerne le filetage et WinForm, vous pouvez jeter un oeil sur le lien ci-dessous juste pour avoir une idée sur la considération que vous devriez faire avant de propriété sous forme de victoire d'accès d'un autre thread

In WinForms, why can't you update UI controls from other threads?

Questions connexes