2009-04-06 5 views
0

J'utilise un CAsyncSocket MFC pour effectuer une communication réseau dans un environnement multithread. Après plusieurs heures d'essai pour que les sockets acceptées acceptent les données entrantes, je suis tombé sur une page qui indique que pour qu'une fonction OnReceive de CAsyncSocket soit appelée, le socket doit être dans le contexte du thread graphique principal. Le déplacer vers le thread principal de l'interface graphique a permis au socket de commencer à recevoir des données.CAsyncSocket et thread

Ma question est la suivante: est-ce que quelqu'un sait d'une solution de contournement pour cela? Le socket était sur un thread graphique avant et OnAccept était appelé bien. Le socket accepté pourrait être utilisé pour envoyer des données sans problème, ne pouvait tout simplement rien recevoir. Je préfère ne pas avoir à ré-architecturer cette partie du logiciel si je peux l'éviter.

Répondre

3

Serait-il plus simple de créer un thread distinct avec sa propre file d'attente de messages pour vos sockets? Je ne pense pas que CAsyncSocket doive être créé dans la file d'attente de messages principale, juste une file d'attente de messages. Consultez la documentation de CWinThread pour voir comment créer un thread distinct avec sa propre file d'attente de messages compatible MFC.

Malheureusement, il est crucial d'appeler toutes les opérations de socket dans le contexte du nouveau thread. MFC utilise l'état global dans les classes masquées qui utilisent le stockage local-thread pour stocker les informations par thread, et cette information est utilisée dans la plupart des méthodes de CAsynchSocket. Cela signifie que CAsynchSocket a une affinité avec les threads et vous devez toujours l'utiliser et le créer dans n'importe quel thread qui sera son pompage de message. Une approche serait de créer un CWinThread, créer votre propre fenêtre cachée MFC personnalisée sur ce thread (en créant la fenêtre dans le contexte de ce thread), et créer des messages et des gestionnaires de messages sur cette fenêtre pour l'ensemble du socket opérations (création, connexion, etc) que vous faites. Assurez-vous que le thread est en train de pomper des messages (la méthode "Run()" le fait), puis envoyez/envoyez des messages à votre fenêtre pour contrôler vos socket (s). De plus, rappelez-vous que les rappels de votre socket se feront sur un thread distinct de celui de votre interface utilisateur ou de vos threads de travail. Vous devez vous préoccuper des conditions de course et éventuellement des problèmes d'affinité des threads de l'interface graphique si vous mettez à jour les objets de l'interface graphique. Si vous êtes préoccupé par l'impact de la conception, créez simplement votre propre objet proxy CThreadSafeAsynchSocket et déléguez-le à l'implémentation réelle en passant des messages à votre fenêtre masquée. Vous pouvez utiliser SendMessage pour les opérations de blocage et PostMessage pour les opérations asynchrones. Si vous enveloppez le constructeur dans un objet d'usine, vous pouvez retarder la création du thread de socket jusqu'à ce que ce soit nécessaire.

La dernière préoccupation que je peux penser est que vous aurez besoin de détecter quand tous vos proxys ont disparu et fermer le fil. Vous pouvez utiliser un nombre de références global géré par les constructeurs/destructeurs de CThreadSafeAsynchSocket pour détecter quand arrêter le thread. Si vous ne parvenez pas à fermer le fil, votre application restera traîner avec une fenêtre masquée même après avoir fermé la fenêtre principale de votre application.

+0

Mon code d'origine utilisait un thread avec une pompe de message (testé et fonctionnant avec l'envoi par le socket) mais ne permettait toujours pas l'appel à OnReceive. – Noaki

+0

Essayez un thread graphique complet avec une fenêtre cachée. –

Questions connexes