2010-09-29 6 views
2

J'ai un programme de formulaires Windows avec une forme MainForm. En appuyant sur un bouton, je lance un code qui s'exécute (impulsions) tous les 0,5secs sur un autre thread. Je veux modifier beaucoup de choses, comme les labels, les barres de progression sur mon MainForm, à partir de la méthode Pulse. Comment est-ce possible? Donc, je voudrais savoir, comment interagir avec les variables, les valeurs, dans ce thread, et le MainForm. Modifiez-vous les uns les autres, etc.Comment passer des valeurs entre threads?

Cliquez sur le bouton foo, je dis à mon pulsateur de commencer. Pulsator.Initialize();

Voici la classe Pulsator:

public static class Pulsator 
{ 
    private static Thread _worker; 

    public static void Initialize() 
    { 
     _worker = new Thread(Pulse); 
     _worker.IsBackground = true; 
     _worker.Start(); 
    } 

    public static void Close() 
    { 
     if (_worker != null) 
     { 
      _worker.Abort(); 
      while (_worker.IsAlive || _worker.ThreadState != ThreadState.Stopped) 
      { 
       //closing 
      } 
     } 
    } 

    public static void Pulse() 
    { 
     if (_worker != null) 
     { 
      while (true) 
      { 
       SomeOtherClass.Pulse(); 
       Thread.Sleep(500); 
      } 
     } 
     else 
     { 
      SomeOtherClass.Pulse(); // yeah I know this doesnt needed 
     } 
    } 
} 

SomeOtherClass méthode d'impulsion ressemble à:

public static void Pulse() 
    { 
     //here I will have several values, variables, and I want to show results, 
     // values on my MainForm, like: 
     Random random = new Random(); 
     MainForm.label1.Text = random.Next(123,321).ToString(); // I hope you know what I mean 
    } 

Bien sûr, il est beaucoup plus compliqué, il est juste un exemple stupide.

+0

Veuillez également noter que l'appel de Thread.Abort lève une exception ThreadAbortException que vous devrez prendre en compte dans votre méthode Close http://msdn.microsoft.com/en-us/library/system.threading.thread.abort. aspx – w69rdy

Répondre

1

Comme d'autres déjà mentionnés, vous devez utiliser Control.Invoke pour modifier les contrôles de l'interface utilisateur du fil d'arrière-plan.

Une autre option consiste à utiliser System.ComponentModel.BackgroundWorker (disponible dans la boîte à outils du concepteur de formulaire). Vous pouvez ensuite utiliser un minuteur de formulaires standard pour appeler la méthode RunWorkerAsync et effectuer votre travail en arrière-plan dans le gestionnaire d'événements DoWork, qui est appelé automatiquement à partir d'un autre thread. À partir de là, vous pouvez remettre les données au thread principal en appelant ReportProgress. Cela déclenchera l'événement ProgressChanged dans le thread principal, où vous êtes libre de mettre à jour tous vos contrôles d'interface utilisateur.

4

Généralement, dans WinForms, il n'est pas prudent de modifier l'état des contrôles visuels en dehors du thread qui possède les ressources non managées sous-jacentes du contrôle (handle de fenêtre). Vous devez utiliser la méthode Control.Invoke pour planifier l'exécution de la modification sur le thread propriétaire du contrôle.

0

C# 2 ou supérieur (VS2005) a des délégués anonymes (et C# 3 a des lambdas qui sont une version légèrement plus propre de la même idée).

Ils permettent à un thread d'être démarré avec une fonction qui peut "voir" des variables dans la portée environnante. Il n'y a donc pas besoin de passer explicitement quelque chose. En revanche, il existe un risque que le thread dépende accidentellement de quelque chose qu'il ne devrait pas (par exemple, une variable qui change dans d'autres threads).

_worker = new Thread(delegate 
{ 
    // can refer to variables in enclosing scope(s). 
}); 
1

Pourquoi ne pas utiliser un System.Timers.Timer?

.: par exemple

 trainPassageTimer = new Timer(500); 
     trainPassageTimer.AutoReset = true; 
     trainPassageTimer.Elapsed += TimeElapsed; 

     ... 

     private void TimeElapsed(object sender, ElapsedEventArgs elapsedEventArgs) 
     { 
// Do stuff 
// Remember to use BeginInvoke or Invoke to access Windows.Forms controls 
     } 
+0

System.Windows.Forms.Timer serait un meilleur choix pour faire de l'interface utilisateur: http://msdn.microsoft.com/msdnmag/issues/04/02/TimersinNET/default.aspx – lesscode

Questions connexes