Dans le code que tu présentes, tu as rendu le modèle de connection asynchrone... synchrone Tout cela parceque tu utilises un ManualResetEvent pour bloquer la fonction qui rend la connection asynchrone, ce qui est complètement inutile.
Le principe du modèle asynchrone est de démarrer le traitement d'une commande (ici la connection d'un socket) dans une thread séparée. L'argument AsyncCallback que tu passes à la fonction BeginConnect sert à fournir un delegate qui sera appelé lorsque la connection sera effectuée.
Ici, tu appelles la fonction BeginConnect puis tu bloques sur un event dans un handler d'évenement WinForms, ce qui a certainement pour effet de te bloquer ton application tant que la connection n'est pas effectuée. Dans le pire des cas, tu peux ne jamais sortir de cette fonction si la connection n'est pas établie...
Tout l'intéret de l'asynchrone ici est justement de ne pas bloquer ta GUI et d'effectuer les traitement qui prennent du temps en arrière plan.
Ainsi tu feras plutôt quelque chose du style :
Code :
- private delegate void ConnectDoneHandler(string message);
- Socket _socket = null;
- private void cmdaConnexion_Click(object sender, System.EventArgs e)
- {
- IPAddress address = IPAddress.Parse("192.168.0.1" );
- IPEndPoint server = new IPEndPoint(address, 8221);
- _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- _socket.BeginConnect(Serveur, new AsyncCallback(ConnectCallback), socWorker);
- }
- private void ConnectCallback(IAsyncResult result)
- {
- try {
- _socket.EndAccept(result);
- // Do some read operations, asynchronously
- // _socket.BeginReceive(...);
- // Mandatory for GUI update operations
- BeginInvoke(new ConnectDoneHandler(OnConnectDone),
- new object[]{ "Connection established..." });
- }
- catch(Exception e) {
- Console.WriteLine(e);
- }
- }
- private void OnConnectDone(string message)
- {
- myLabel.Text = message;
- }
|
Il faut savoir également qu'intégrer des éléments réseau dans le code de la GUI est une très mauvaise pratique. Il faut créer un objet séparé et effectuer la communication grâce à des méthodes et évènements.
.NET facilite le développement de composants, il faut donc en profiter. Tu pourras donc créer un objet dans le style :
Code :
- public class MyNetworkManager
- {
- public event EventHandler Connected;
- public event EventHandler ConnectionFailed;
- private Socket _socket;
- private IPEndPoint _serverEndPoint;
- public MyNetworkManager(IPAddress address, int port)
- {
- _serverEndPoint = new IPEndPoint(address, port);
- }
- public void Connect()
- {
- _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- _socket.BeginConnect(_serverEndPoint, new AsyncCallback(ConnectDone), null);
- }
- private void ConnectDone(IAsyncResult result)
- {
- try
- {
- _socket.EndConnect(result);
- OnConnectDone();
- // Start async reading...
- }
- catch(Exception /* e */)
- {
- OnConnectionFailed();
- }
- }
- private void OnConnectDone()
- {
- if(Connected != null)
- Connected(this, new EventArgs());
- }
- private void OnConnectionFailed()
- {
- if(ConnectionFailed != null)
- ConnectionFailed(this, new EventArgs());
- }
- }
|
Tu pourras utiliser l'objet de cette manière :
Code :
- MyNetworkManager manager = new MyNetworkManager(IPAddress.Parse("192.168.0.1" ), 1234);
- // Hook some events
- manager.Connected += new EventHandler(OnManagerConnected);
- manager.ConnectionFailed += new EventHandler(OnManagerConnectionFailed);
- // Then begin the connection
- manager.Connect();
|
Tu auras certainement remarqué l'utilisation de Control.BeginInvoke dans mon premier exemple : Cela permet de mettre à jour proprement l'interface graphique depuis une autre thread que la thread principale.
Tu pourras trouver des articles ici et ici traitant de ce sujet.
Le fonctionnement asynchrone est très puissant mais il amène son lot de problèmes qu'il faut gérer...
--
Jay
{Epitech.}
http://www.labtech.epitech.net/blogs
Message édité par jaylee le 31-05-2004 à 14:03:00