2010-12-15 97 views
4

Nouveau à C# si nue avec moi. Comment vous mettez à jour les zones de texte et les étiquettes dans le thread principal à partir d'un nouveau thread exécutant une classe différente.Comment mettre à jour des zones de texte dans le fil principal à partir d'un autre fil?

MainForm.cs (filetage principal)

public partial class MainForm : Form 
{ 
    public MainForm() 
    { 
     Test t = new Test(); 

     Thread testThread = new Thread(new ThreadStart(t.HelloWorld)); 
     testThread.IsBackground = true; 
     testThread.Start(); 
    } 

    private void UpdateTextBox(string text) 
    { 
     textBox1.AppendText(text + "\r\n"); 
    } 

} 

public class Test 
{ 
    public void HelloWorld() 
    { 
     MainForm.UpdateTextBox("Hello World"); 
     // How do I execute this on the main thread ??? 
    } 
} 

j'ai regardé les exemples sur ce site mais cant semblent bien faire les choses. S'il vous plaît quelqu'un pourrait-il donner de bons liens.

J'ai recommencé à zéro afin de ne pas gâcher mon code. Si quelqu'un veut mettre en place un exemple de travail avec mon exemple, ce serait génial.

De plus, si je devais mettre à jour plusieurs objets comme des zones de texte et des étiquettes (pas tous en même temps), quelle serait la meilleure façon d'y arriver, d'avoir une méthode pour chaque zone de texte ou y a-t-il un moyen? avec une méthode? Comme je l'ai dit je suis nouveau, alors parlez lentement :)

+0

bienvenue à ALORS. Vous pouvez modifier votre question pour ajouter des informations supplémentaires, et vous pouvez laisser des commentaires sur les réponses à une question que vous avez posée (et sur n'importe quoi après avoir atteint 50 rep). – Will

Répondre

3

Vous pouvez appeler le BeginInvoke method, qui va mettre en file d'attente un délégué à exécuter de manière asynchrone sur le thread de l'interface utilisateur.

Si vous avez besoin du thread d'arrière-plan pour attendre que la fonction se termine sur le thread d'interface utilisateur, vous pouvez appeler Invoke à la place.

Notez que vous aurez besoin d'une référence à l'instance de votre formulaire; vous devriez probablement passer cela au constructeur Test et le stocker dans un champ privé.


Le BackgroundWorker component fera tout cela automatiquement en utilisant la méthode ReportProgress; vous devriez envisager de l'utiliser.

+0

Merci pour la réponse, mais im nouveau à C# et aurait besoin d'un exemple à travailler pour que je puisse comprendre comment cela fonctionne. – tiptopjones

+1

@tiptop: Alors vous devriez probablement utiliser un BackgroundWorker. [MSDN a des exemples] (http://msdn.microsoft.com/en-us/library/waw3xexc.aspx). – SLaks

+0

Tout développeur WinForms doit comprendre comment mettre à jour l'interface utilisateur d'une manière threadsafe, et les deux approches sont des options valides pour comprendre – STW

6

Appel ou DébutInvoke, par ex.

Invoke((MethodInvoker)delegate { 
    MainForm.UpdateTextBox("Hello World"); 
}); 

@tiptopjones Je suppose que vous vous demandez également comment obtenir une référence à la forme. Vous pouvez rendre votre méthode HelloWorld prendre un paramètre d'objet, utiliser le délégué ParameterizedThreadStart, puis passer une référence au formulaire en tant que paramètre à la méthode Thread.Start. Mais je suggère de lire sur les méthodes anonymes qui le rend beaucoup plus facile et garde tout fortement typé.

public class MainForm : Form { 
    public MainForm() { 
     Test t = new Test(); 

     Thread testThread = new Thread((ThreadStart)delegate { t.HelloWorld(this); }); 
     testThread.IsBackground = true; 
     testThread.Start(); 
    } 

    public void UpdateTextBox(string text) { 
     Invoke((MethodInvoker)delegate { 
      textBox1.AppendText(text + "\r\n"); 
     }); 
    } 
} 

public class Test { 
    public void HelloWorld(MainForm form) { 
     form.UpdateTextBox("Hello World"); 
    } 
} 

Lorsque vous obtenez à l'aise avec ce que vous pouvez lire sur les expressions lambda et le faire comme:

Thread testThread = new Thread(() => t.HelloWorld(this)); 
+0

Hey, il est préférable de modifier votre question pour ajouter plus d'informations plutôt que de fournir une autre réponse. – Will

1

La façon preferred dans WinForms est d'utiliser le SynchronizationContext

public partial class MainForm : Form 
{ 
    SynchronizationContext ctx; 

    public MainForm() 
    { 
     ctx = SynchronizationContext.Current; 

     Test t = new Test(); 

     Thread testThread = new Thread(new ThreadStart(t.HelloWorld)); 
     testThread.IsBackground = true; 
     testThread.Start(); 
    } 

    private void UpdateTextBox(string text) 
    { 
     ctx.Send(delegate(object state) 
     { 
      textBox1.AppendText(text + "\r\n"); 

     },null); 
    }  
} 

public class Test 
{ 
    public void HelloWorld() 
    { 
     MainForm.UpdateTextBox("Hello World"); 
     // How do I excute this on the main thread ??? 
    } 
}