2009-10-06 8 views
0

J'essaie de gérer socket dans différents threads créant une défaillance d'exécution. Voir le code suivant. J'appelle Lock() à partir d'un thread et Unlock() à partir d'autres threads. Quand il exécute CSocket :: Close() il donne une exception.Comment gérer la même socket dans différents threads?

J'ai cherché sur Google pour ce bug et j'ai des raisons. Cela se produit parce que; un objet CSocket ne doit être utilisé que dans le contexte d'un seul thread car le descripteur SOCKET encapsulé par un objet CAsyncSocket est stocké dans un mappage de handle par thread. Ils suggèrent également une solution en partageant les poignées SOCKET entre les threads (http://support.microsoft.com/kb/175668). Mais ce n'est pas possible dans mon cas puisque j'excepte un rappel de notification qui ne fonctionnera pas avec la solution ci-dessus. Quelqu'un peut-il suggérer un mécanisme pour partager CSocket entre les threads sans effectuer de rappels de notification?

+0

BTW, en utilisant ++ et - comme cela dans un environnement multithread ne fonctionnera pas car ces opérations ne sont pas garanties pour être atomique. Vous pouvez utiliser InterlockedIncrement() et InterlockedDecrement() pour obtenir l'atomicité. Pas lié au problème auquel vous faites face, mais gardez à l'esprit. – Naveen

+0

@Naveen - Merci pour le conseil – Vadakkumpadath

Répondre

1

Si, comme vous le dites, "un objet CSocket ne doit être utilisé que dans le contexte d'un seul thread," alors il n'y a pas de "mécanisme pour partager CSocket entre les threads". En d'autres termes, l'un des threads doit posséder le CSocket, et les autres ne peuvent pas jouer avec lui.

Dans de tels cas, la solution consiste à utiliser un système de messagerie inter-thread. De cette façon, l'un des autres fils peut envoyer un message au propriétaire en lui disant: "Hé, mon pote, ferme ta prise!"

Les détails de la façon dont vous feriez cette messagerie dépendent entièrement du contexte de votre programme.

3

Vous coould juste utiliser la prise directement et arrêtez d'utiliser le, de toute évidence, viciée implémentation MFC ...

+0

Je suis généralement d'accord, mais si ce n'est pas une option, voir ma réponse. –

1

Je vous conseille d'utiliser un niveau plus élevé (et moins buggé) API socket comme Boost.Asio. Notez qu'il ne fait pas de socket thread-safe de toute façon (voir there). Vous devez utiliser une fonction de verrouillage/déverrouillage. Je ne suis pas sûr de comprendre votre question sur le partage des sockets entre threads sans utiliser les rappels de notification. Entre les threads T1 et T2, en supposant que T1 gère une socket, il n'y a que deux façons pour T2 de prendre connaissance d'un événement socket. Soit une notification lancée par T1, soit une question posée par T2 à T1, soit régulièrement, soit dans un appel bloquant.

+0

Merci. Je peux ajouter plus de détails. Prise partagée écoutant réellement les connexions. Ainsi, T1 appellera CSocket :: Create() et CSocket commencera à écouter. Lorsque T2 est démarré, il incrémente le m_LockCount. Supposons maintenant que T1 s'est arrêté. Il va décrémenter m_LockCount. Après que T2 s'est arrêté. T2 décrémentera m_LockCount à 0 et appellera CSocket :: Close(). J'espère que vous comprenez la façon dont je suis censé partager. – Vadakkumpadath

+0

"parce que le descripteur SOCKET encapsulé par un objet CAsyncSocket est stocké dans un mappage de handle par thread" Selon ceci, le handle du socket serait perdu si T1 se fermait, donc T2 ne devrait pas être capable de le fermer. – Gayan

Questions connexes