2009-03-03 9 views
1

Dans le code suivant MessageReceived est sur un thread différent de label1 et en essayant d'y accéder j'obtenir cette erreur:besoin d'aide pour « erreur de fonctionnement inter-threads » en C#

Cross-thread operation not valid: Control 'label1' accessed from a thread other than the thread it was created on.

foo.MessageReceived += new Agent.MessageReceivedHandler(foo_MessageReceived); 

void foo_MessageReceived(Message message) 
{ 
    label1.Text = message.Body; 
}  

Comment puis-je resoudre ceci?

Plus: apparemment je dois utiliser delegate et invoke, mais je ne sais pas comment, pouvez-vous s'il vous plaît expliquer plus en détail?

+1

double exact (pas NPR, comme je l'ai tort cliqué): http://stackoverflow.com/questions/244591 http://stackoverflow.com/questions/142003 http://stackoverflow.com/questions/ 470390 entre autres. –

Répondre

0

Assurez-vous toujours que vous mettez à jour votre interface graphique sur le thread principal (fil GUI).

foo.MessageReceived + = nouveau Agent.MessageReceivedHandler (foo_MessageReceived);

public delegate void MyDelegate(Message msg); 
void foo_MessageReceived(Message message) 
{ 
    if (InvokeRequired) 
    { 
     BeginInvoke(new MyDelegate(foo_MessageReceived),new object[]{message}); 
    } 
    else 
    { 
     label1.Text = message.Body; 
    } 
} 
0

Ceci n'est absolument pas utile. Je voudrais pouvoir voter moi-même.

Je ne suis peut-être pas à jour, mais d'après ce dont je me souviens, vous n'êtes pas autorisé à modifier quoi que ce soit dans l'interface graphique à partir de tout sauf du fil principal. Déléguer la mise à jour de l'étiquette au thread qui a créé l'étiquette au lieu d'essayer de la mettre à jour directement.

4

Espérons que cela sera fermé comme une copie exacte, mais sinon:

Ne touchez pas l'interface graphique d'un fil non-GUI. Utilisez BackgroundWorker et signalez la progression de manière appropriée, ou lisez the WinForms page of my threading article pour un contrôle plus direct (Control.Invoke/BeginInvoke).

0

Dans votre classe Agent, lorsque vous déclenchez l'événement MessageReceived, vous devez vérifier si la cible du gestionnaire d'événements implémente ISynchronizeInvoke. Si tel est le cas, et si la propriété InvokeRequired renvoie true, vous devrez appeler le gestionnaire d'événement.

Si vous n'utilisez pas WinForms, mais WPF, vous ne pouvez plus compter sur ISynchronizeInvoke car les contrôles WPF n'implémentent pas cette interface. Au lieu de cela, vous devrez travailler avec AsyncOperation et AsyncOperatoinManager.

1

Vous devez utiliser Control.Invoke (ou Control.BeginInvoke). Tout d'abord, créez une nouvelle application Windows Forms et ajoutez une étiquette et un bouton. Double-cliquez sur le bouton dans Visual Studio pour modifier cliquons événement et ajoutez le code suivant:

private void button1_Click(object sender, EventArgs e) 
    { 
     new System.Threading.Thread(new System.Threading.ThreadStart(Run)).Start(); 
    } 

    void Run() 
    { 
     label1.Invoke(new Action(delegate() 
     { 
      label1.Text = System.Threading.Thread.CurrentThread.Name + " " + System.DateTime.Now.ToString(); 
     })); 
    } 
+0

L'élément clé requis de cette réponse est l'appel Invoke. – ConsultUtah

Questions connexes