Mettre à jour la zone de texte à partir de la boucle dans backgroundworker

Je sais que cette question est un peu posée (du moins d’après ce que j’ai trouvé ici jusqu’à présent), mais je ne peux pas vraiment en comprendre le sens. Déjà essayé avec l’exemple de msdn mais toujours pas de succès. Voici ce que j’essaie de faire: j’ai un compteur USB connecté à une règle TLL. Je veux lire la valeur constamment dans une boucle et écrire la lecture dans une zone de texte sans bloquer l’interface utilisateur principale. D’autres questions me disent que je devrais utiliser Invoke ou Backgroundworker, mais je n’ai pas vraiment trouvé d’exemple que j’ai compris et que je pourrais utiliser pour ajuster mon code en conséquence. Le code sans aucune modification, pour restr simple, est le suivant:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; using System.Windows.Forms; namespace USB_Counter { public partial class Form1 : Form { [DllImport("HS_UC.dll", EntryPoint = "HS_UC_Close")] //+further DLL imports (driver for USBCounter) public static extern int HS_UC_Close(int CounterNo); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) //initialize COunter { int A = HS_UC_Init(1, 3); ssortingng B = Convert.ToSsortingng(A); MessageBox.Show(B); //to check if there is no error } private void button2_Click(object sender, EventArgs e) { HS_UC_SetDistCode(1, 20, 40, 4, 0, 0); //set Reference HS_UC_SetRefMode(1, 1); } private void button3_Click(object sender, EventArgs e) { int a = 1; int A = 0; //variable that takes counter value (the one I want) int B = 0; //variable that takes counter status do { HS_UC_GetCounter(1, ref A, ref B); decimal C = (Convert.ToDecimal(A) / 100); textBox1.Text = "Das ist: " + C; textBox1.Update(); } while (a == 1); } } 

}

Maintenant cela fonctionne comme un intendet, mais comme mentionné, il bloque le fil principal de l’interface utilisateur (évidemment). Si quelqu’un trouvait une question similaire avec des astuces utiles pour bien commencer avec ce sujet multithreading ou des astuces utiles concernant ma question directement, ce serait grandement apprécié. Cordialement de Berlin, Chris

Mise à jour: ça marche avec la tentative suivante:

 private void Counter_Read() { int a = 1; do { int A = 0; int B = 0; HS_UC_GetCounter(1, ref A, ref B); decimal C = (Convert.ToDecimal(A) / 100); UpdateTextBox(C); } while (a == 1); } public void UpdateTextBox(decimal C) { if (InvokeRequired) { this.Invoke(new Action(UpdateTextBox), new object[] { C }); return; } textBox1.Text = "Das ist: " + C; textBox1.Update(); } private void button3_Click(object sender, EventArgs e) { System.Threading.Thread t = new System.Threading.Thread(() => Counter_Read()); t.Start(); } 

À partir de cela, je reçois une sortie décimale que je mets à jour en permanence et qui est encore capable d’utiliser les autres boutons.

externaliser le code de la boucle dans une méthode. Dans la méthode, vous devrez utiliser BeginInvoke pour écrire dans la zone de TextBox

 private void DoTheLoop() { int a = 1; int A = 0; //variable that takes counter value (the one I want) int B = 0; //variable that takes counter status do { HS_UC_GetCounter(1, ref A, ref B); decimal C = (Convert.ToDecimal(A) / 100); textBox1.BeginInvoke(new Action(()=>{textBox1.Text = "Das ist: " + C;})); } while (a == 1); } 

Première version utilisant un thread normal:

Créez un thread et démarrez-le avec la nouvelle méthode en button3 bouton 3

 private void button3_Click(object sender, EventArgs e) { System.Threading.Thread t = new System.Threading.Thread(()=>DoTheLoop()); t.Start(); } 

Cela ne devrait pas bloquer votre interface graphique et la zone de texte affichera les valeurs

Deuxième version utilisant un BackgroundWorker :

Créez un BackgroundWorker et enregistrez l’événement DoWork :

 System.ComponentModel.BackgroundWorker worker = new System.ComponentModel.BackgroundWorker(); private void Form1_Load(object sender, EventArgs e) { worker.DoWork += Worker_DoWork; } 

à l’intérieur du gestionnaire d’événements, appelez la même méthode DoTheLoop() :

 private void Worker_DoWork(object sender, DoWorkEventArgs e) { DoTheLoop(); } 

démarrer le travailleur dans l’événement de clic de bouton:

 private void button1_Click(object sender, EventArgs e) { worker.RunWorkerAsync(); } 

Même résultat à la fin 🙂

Vous voudrez peut-être jeter un oeil à ce lien MSDN .

Toutefois, un conseil rapide consisterait à enregistrer une méthode pour l’événement DoWork , puis à exécuter la méthode RunAsynchronously .