2010-03-31 3 views
3

J'ai créé une interface graphique (winforms) et ajouté un backgroundworker pour l'exécuter dans un thread séparé. L'arrière-plan doit mettre à jour 2 étiquettes en continu. Le thread d'arrière-plan devrait démarrer avec button1 click and run forever.Mise à jour continue de l'interface graphique C# à partir de l'arrière-plan

class EcuData 
    { 
     public int RPM { get; set; } 
     public int MAP { get; set; } 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     EcuData data = new EcuData 
     { 
      RPM = 0, 
      MAP = 0 
     }; 
     BackWorker1.RunWorkerAsync(data); 
    } 

    private void BackWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     EcuData argumentData = e.Argument as EcuData; 
     int x = 0; 
     while (x<=10) 
     { 
      // 
      // Code for reading in data from hardware. 
      // 
      argumentData.RPM = x;   //x is for testing only! 
      argumentData.MAP = x * 2;  //x is for testing only! 
      e.Result = argumentData; 
      Thread.Sleep(100); 
      x++; 
     } 
    private void BackWorker1_RunWorkerCompleted_1(object sender, RunWorkerCompletedEventArgs e) 
    { 
     EcuData data = e.Result as EcuData; 
     label1.Text = data.RPM.ToString(); 
     label2.Text = data.MAP.ToString(); 
    } 
} 

Le code ci-dessus juste mis à jour l'interface graphique quand BackgroundWorker est fait avec son travail, et ce n'est pas ce que je cherche.

Répondre

9

Vous devez regarder BackgroundWorker.ReportProgess.

Vous pouvez l'utiliser pour renvoyer périodiquement un objet à une méthode dans le thread principal, qui peut mettre à jour les étiquettes pour vous.

1
class EcuData 
    { 
     public int RPM { get; set; } 
     public int MAP { get; set; } 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     EcuData data = new EcuData 
     { 
      RPM = 0, 
      MAP = 0 
     }; 
     BackWorker1.RunWorkerAsync(data); 
    } 

    private void BackWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     EcuData argumentData = e.Argument as EcuData; 
     int x = 0; 
     while (x<=10) 
     { 
      e.Result = argumentData; 
      Thread.Sleep(100); 
      this.Invoke((MethodInvoker)delegate 
      { 
       label1.Text = Convert.ToString(argumentData.RPM = x);   //send hardware data later instead, x is for testing only! 
       label2.Text = Convert.ToString(argumentData.MAP = x * 2);  //send hardware data later instead, x is for testing only! 
      }); 
      x++; 
     } 
    } 

Cela fonctionne, mais c'est la bonne façon de le faire?

+0

Non, jetez un oeil à la réponse de Blorgbeard – tanascius

3

Vous pouvez utiliser un System.Threading.Timer et mettre à jour l'interface utilisateur à partir de la méthode de rappel du temporisateur en appelant BeginInvoke sur le formulaire principal.

uiUpdateTimer = new System.Threading.Timer(new TimerCallback(
      UpdateUI), null, 200, 200); 

private void UpdateUI(object state) 
{ 
    this.BeginInvoke(new MethodInvoker(UpdateUI)); 
} 

private void UpdateUI() 
{ 
    // modify labels here 
} 
Questions connexes