2010-10-26 4 views
-1
using System; 
using System.Windows.Forms; 
using agsXMPP; 
using System.Text; 
namespace iTalk2 
{ 
    public partial class Main : Form 
    { 
     agsXMPP.XmppClientConnection objXmpp; 

     public Main() 
     { 
      InitializeComponent(); 
     } 


     private void Form1_Load(object sender, EventArgs e) 
     { 

      Console.WriteLine("Logging in. Please wait..."); 
      Console.ReadLine(); 
      objXmpp = new agsXMPP.XmppClientConnection(); 
      agsXMPP.Jid jid = null; 
      jid = new agsXMPP.Jid("username" + "@gmail.com"); 
      objXmpp.Password = "password"; 
      objXmpp.Username = jid.User; 
      objXmpp.Server = jid.Server; 
      objXmpp.AutoResolveConnectServer = true; 

      try 
      { 
       objXmpp.OnMessage += messageReceived; 
       objXmpp.OnAuthError += loginFailed; 
       objXmpp.OnLogin += loggedIn; 
       objXmpp.Open(); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.Message); 
       Console.ReadLine(); 
      } 
     } 

     private void messageReceived(object sender, agsXMPP.protocol.client.Message msg) 
     { 
      string[] chatMessage = null; 
      chatMessage = msg.From.ToString().Split('/'); 
      agsXMPP.Jid jid = null; 
      jid = new agsXMPP.Jid(chatMessage[0]); 
      agsXMPP.protocol.client.Message autoReply = null; 
      autoReply = new agsXMPP.protocol.client.Message(jid, agsXMPP.protocol.client.MessageType.chat, "This is a test"); 
      objXmpp.Send(autoReply); 
     } 

     private void loginFailed(object o, agsXMPP.Xml.Dom.Element el) 
     { 
      Console.WriteLine("Login failed. Please check your details."); 
     } 

     private void loggedIn(object o) 
     { 
      Console.WriteLine("Logged in and Active."); 
      lblStatus.Text = "Online"; 
     } 

     private void txtUsername_TextChanged(object sender, EventArgs e) 
     { 

     } 

     private void label1_Click(object sender, EventArgs e) 
     { 

     } 

     private void label2_Click(object sender, EventArgs e) 
     { 

     } 

     private void txtPassword_TextChanged(object sender, EventArgs e) 
     { 

     } 

     private void btnlogin_Click(object sender, EventArgs e) 
     { 

     } 

    } 

} 

Ce code ne fonctionne pas. la fonction 'loggedIn (object o)' ne fonctionne pas. il dit que le lblStatus (qui est une étiquette) est sur un autre thread. la fenêtre d'erreur indique "Opération croisée pas valide: Contrôle 'lblStatus' accédé à partir d'un thread autre que le fil sur lequel il a été créé." Merci d'avance.appel de thread croisé

+1

duplication possible de [Opération croisée non valide: contrôle accédé à partir d'un thread autre que le thread sur lequel il a été créé.] (Http://stackoverflow.com/questions/142003/cross-thread-operation-not- valid-control-accédé-à partir d'un thread-autre-que-le-t) – spender

+0

Avez-vous même fait une recherche? – spender

+0

oui, j'ai cherché mais je ne peux pas comprendre les autres discussions. Je suis nouveau à la programmation. – vishnu

Répondre

2

Vous devez appeler un appel sur le thread UI. Si vous ajoutez le code comme suit en haut de la méthode loggedIn il devrait fonctionner: -

if(InvokeRequired) 
{ 
    Invoke(new Action<object>(loggedIn), o); 
    return; 
} 
+0

cela a fonctionné. Pouvez-vous expliquer ce qui se passe? – vishnu

+0

Bien sûr. Dans les applications WinForm, il y a un thread qui traite spécifiquement toute l'interface utilisateur. Toutes les opérations se produisent dans ce thread sauf si vous déclenchez un thread séparé pour faire autre chose. loggedIn est rappelé sur un thread différent, il faut donc que le thread UI l'exécute afin de mettre à jour le label. InvokeRequired est une propriété de Forms qui indique si vous êtes sur le thread de l'interface utilisateur ou non (true si ce n'est pas le cas), si c'est le cas, vous devez appeler l'appel sur le thread d'origine. Comme @Ani souligne ces blocs (c.-à-d.ne finit pas avant d'avoir fini), vous * pourriez * utiliser BeginInvoke pour le faire en arrière-plan. – ljs

+0

(en continuant d'en haut ...) mais dans ce cas, juste en mettant à jour une étiquette, il ne semble pas nécessaire, sauf si cet autre thread doit faire un autre travail. Phew! – ljs

1

WinForms est conçu de sorte que les contrôles doivent être manipulés uniquement sur le thread UI, le thread qui exécute la boucle de messages qui gère le contrôle.

Essayez ceci:

private void loggedIn(object o) 
{ 
    Console.WriteLine("Logged in and Active."); 
    Action act =() => lblStatus.Text = "Online"; 
    Invoke(act); 
} 

Si votre application est telle que cette méthode peut être appelée sur le thread d'interface utilisateur ou un thread de travail séparé, vous seriez test mieux pour InvokeRequired (simplement: suis-je sur le fil d'interface utilisateur du contrôle?) et traiter le résultat de manière appropriée. Par exemple,

private void loggedIn(object o) 
{ 
    if(InvokeRequired) 
     Invoke(new Action<object>(loggedIn), o);   
    else 
    { 
     Console.WriteLine("Logged in and Active."); 
     lblStatus.Text = "Online";   
    } 
} 

Notez que Invoke sera bloc jusqu'à ce que l'interface de mise à jour est terminée. Si vous voulez quelque chose de plus fire-and-forget, utilisez plutôt BeginInvoke.

+0

pls expliquer ces deux lignes Action act =() => lblStatus.Text = "En ligne"; Appel (action); – vishnu

+0

Cela crée un délégué de type 'Action' à travers une expression lambda, puis l'appelle sur le thread UI. – Ani

0

Lorsque vous lancez une application, il est en cours d'exécution à partir d'un seul fil. C'est le thread principal, parfois appelé le thread UI (puisque l'interface utilisateur sera généralement rendue au démarrage et par conséquent il sera sur ce thread principal.)

Maintenant, lorsque vous écoutez des événements, vos méthodes/délégués seront Ceci est une conséquence de la conception basée sur les événements.Ce n'est normalement pas un problème, sauf si vous essayez de partager des données entre deux threads.C'est exactement ce qui se passe avec vos éléments d'interface utilisateur. Si vous créez votre premier thread, mais que d'autres threads tentent de mettre à jour sa valeur,

En raison de votre conception, vous devez vérifier si IsInvokeRequired est activé sur le contrôle et, si c'est le cas, utiliser Invoke pour définir la nouvelle valeur. nouveau thread dans le thread principal que votre interface utilisateur est runn sur et vous permettra de changer le contrôle en toute sécurité.

Questions connexes