2011-06-12 4 views
1

Je fais un réseau asynchrone en C# .NET avec les classes TcpClient et TcpListener. J'utilise WinForms pour l'interface graphique.C#/Communication entre le réseau Async et l'interface graphique

Chaque fois que je reçois des données d'un ordinateur distant, l'opération est effectuée sur un thread sous-jacent différent.

Ce que je dois faire est de mettre à jour le GUI de mon application chaque fois que je reçois une réponse de réseau.

// this method is called whenever data is received 
// it's async so it runs on a different thread 
private void OnRead(IAsyncResult result) 
{ 
    // update the GUI here, which runs on the main thread 
    // (a direct modification of the GUI would throw a cross-thread GUI exception) 
} 

Comment puis-je y parvenir?

Répondre

3

Dans Winforms, vous devez utiliser Control.Invoke Method (Delegate) pour vous assurer que le contrôle est mis à jour dans le thread d'interface utilisateur.

Exemple:

public static void PerformInvoke(Control ctrl, Action action) 
{ 
    if (ctrl.InvokeRequired) 
     ctrl.Invoke(action); 
    else 
     action(); 
} 

Utilisation:

PerformInvoke(textBox1,() => { textBox1.Text = "test"; }); 
+0

Réutilisable et très soignée. Merci beaucoup monsieur! – asmo

2

dans l'interface graphique fonction d'écriture comme ceci:

public void f() { 

     MethodInvoker method =() => { 
      // body your function 
     }; 

     if (InvokeRequired) { 
      Invoke(method); // or BeginInvoke(method) if you want to do this asynchrous 
     } else { 
      method(); 
     } 
    } 

si vous dans un autre thread, appelez cette fonction, il appellera dans l'interface graphique fil

0

J'ai ajouté une méthode d'extension au code proposé par Alex. Ça devient encore meilleur!

// Extension method 
public static class GuiHelpers 
{ 
    public static void PerformInvoke(this Control control, Action action) 
    { 
     if (control.InvokeRequired) 
      control.Invoke(action); 
     else 
      action(); 
    } 
} 


// Example of usage 
private void EnableControls() 
{ 
    panelMain.PerformInvoke(delegate { panelMain.Enabled = true; }); 
    linkRegister.PerformInvoke(delegate { linkRegister.Visible = true; }); 
} 
Questions connexes