2010-12-01 40 views
4

J'ai une application C# 2.0 avec un formulaire qui utilise une classe qui contient un thread.Appel Invoke/BeginInvoke à partir d'un thread

Dans la fonction de thread, plutôt que d'appeler le gestionnaire d'événements directement, il est appelé. L'effet est que le formulaire propriétaire n'a pas besoin d'appeler InvokeRequired/BeginInvoke pour mettre à jour ses contrôles.

public class Foo 
{ 
    private Control owner_; 
    Thread thread_; 

    public event EventHandler<EventArgs> FooEvent; 

    public Foo(Control owner) 
    { 
     owner_ = owner; 
     thread_ = new Thread(FooThread); 
     thread_.Start(); 
    } 

    private void FooThread() 
    { 
     Thread.Sleep(1000); 
     for (;;) 
     { 
      // Invoke performed in the thread 
      owner_.Invoke((EventHandler<EventArgs>)InternalFooEvent, 
       new object[] { this, new EventArgs() }); 
      Thread.Sleep(10); 
     } 
    } 

    private void InternalFooEvent(object sender, EventArgs e) 
    { 
     EventHandler<EventArgs> evt = FooEvent; 
     if (evt != null) 
      evt(sender, e); 
    } 
} 

public partial class Form1 : Form 
{ 
    private Foo foo_; 

    public Form1() 
    { 
     InitializeComponent(); 

     foo_ = new Foo(this); 
     foo_.FooEvent += OnFooEvent; 
    } 

    private void OnFooEvent(object sender, EventArgs e) 
    { 
     // does not need to call InvokeRequired/BeginInvoke() 
     label_.Text = "hello"; 
    } 
} 

Ceci est évidemment contraire à la méthode utilisée par les API de Microsoft qui utilisent les threads de fond comme System.Timers.Timer et System.IO.Ports.SerialPort. Y at-il quelque chose de fondamentalement faux avec cette méthode? Est-ce dangereux d'une certaine façon?

Merci, PaulH


Edit: aussi, si la forme n'a pas souscrit à l'événement tout de suite? Souhaitez-vous obstruer la file d'attente des messages du formulaire avec des événements qui ne l'intéressaient pas?

+0

s'il vous plaît voir mon modifier – Falcon

Répondre

3

Ceci est un appel threadsafe, la méthode sera traitée dans le thread du formulaire.

Rien à redire quand on le regarde d'un point de vue conceptuel. Cependant, les minuteries sont plus élégantes pour de telles tâches. Cependant, il se peut qu'une temporisation avec un intervalle de 10 ms ralentisse l'interface graphique, c'est probablement la raison pour laquelle Invoke a été utilisé.

Vous n'avez pas besoin d'un appel à InvokeRequired, car il est clair que le contrôle se trouve dans un autre thread. De plus, BeginInvoke n'a besoin d'être appelé que lorsque vous voulez appeler une méthode de façon asynchrone, ce qui n'est évidemment pas le cas ici.

au sujet de votre édition: Non, la file d'attente de messages ne seront pas colmatées. Aucun événement ne sera déclenché si aucun gestionnaire n'a été enregistré. Un autre regard sur votre code;)