2009-11-17 7 views
1

Je donne les résultats suivants:Threading et Sockets

ThreadStart startThread = 
    delegate 
    { 
      mySocket.StartListen(); 
    }; 

mySocket est maintenant mise en boucle sur un listen() quand je:

new Thread(startThread).Start(); 

Voici StartListen:

public void StartListen() 
{ 
Object locker = new Object(); 

// Lock resources 
lock (locker) 
{ 
    S = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, 
     System.Net.Sockets.SocketType.Stream, 
     System.Net.Sockets.ProtocolType.Tcp); 
    S.Blocking = false; 

    try 
    { 
    S.Bind(serverEP); 
    S.Listen(1000); 
    isListening = true; 

    /* 
    * While statement not required here because AcceptConnection() 
    * method instructs the socket to BeginAccept() again... 
    */ 
    //while (true) 
    //{ 
    connectDone.Reset(); 
    S.BeginAccept(new AsyncCallback(AcceptConnection), Channel); 
    connectDone.WaitOne(); 
    //} 
    } 
    catch (System.Net.Sockets.SocketException SockEx) 
    { 
    Console.WriteLine("*****[" + name + "] " + SockEx.SocketErrorCode + ":"); 
    Console.WriteLine("*****[" + name + "] " + SockEx.Message); 
    } 
} 
} 

En raison de les méthodes asynchrones les choses ne finissent pas vraiment et retournent un signal pour que n'importe quoi d'autre continue. Toutes les commandes que j'implémente après le Thread.Start() ci-dessus ne fonctionnent pas correctement. Par exemple, dans StartListen, notez que j'ai un isListening = true. Après avoir démarré le thread, je veux utiliser la propriété IsListening. Il est toujours retourné comme faux.

Comment démarrer le fil. Une méthode asynchrone (c'est-à-dire ThreadStart.BeginInvoke()) serait-elle préférable? N'est-ce pas similaire à l'utilisation d'un ManualResetEvent?

Répondre

2

Marquez isListening en tant que volatile. Si je comprends bien, vous faites référence à ce drapeau dans deux fils différents. Normalement, les données partagées entre les threads doivent être synchronisées, mais cela ne semble pas être le cas. Cependant, étant donné que le drapeau est un type booléen, vous n'avez techniquement pas besoin de synchroniser l'accès car le framework .NET garantit que les lectures et les écritures des types booléens sont atomiques (I pense je dis cela correctement .. Quelqu'un s'il vous plaît corrigez-moi si ce n'est pas techniquement correct). Mais, afin de s'assurer que les lectures de ce type obtiennent effectivement la valeur la plus récente, vous devez le marquer comme volatile.

En outre, vous seriez mieux d'utiliser la classe TcpListener au lieu d'essayer de le faire avec la classe Socket. Ce que vous faites n'est pas faux, mais la classe TcpListener rendrait votre code plus simple à lire et à maintenir, IMO.

Enfin, l'objet locker que vous utilisez ne fait vraiment rien car il est local à la méthode StartListen(). Pour que les objets de synchronisation aient un effet, ils doivent être accessibles aux threads qui ont besoin d'un accès sérialisé aux données partagées. Comme vous le faites ici, les autres threads ne peuvent pas accéder à la variable locker, la rendant ainsi inutile.

+0

Je n'ai jamais utilisé 'volatile' auparavant. Je vais lire à ce sujet. Utiliser TcpListener n'est pas complètement hors de question. Cependant, toutes les opérations asynchrones sont déjà écrites et fonctionnent avec la classe Sockets. J'ai opté pour travailler avec la classe de base plutôt que de prendre la voie facile sur TcpListener/TcpClient. :) – IAbstract

+0

L'utilisation de la classe 'Socket' n'est pas fausse. C'est juste que 'TcpListener' est beaucoup plus facile car il a été conçu expressément pour la façon dont vous utilisez' Socket'. –