CAsyncSocket和线程

时间:2009-04-06 15:58:40

标签: c++ sockets mfc mfc-networking

我正在使用MFC CAsyncSocket在多线程环境中进行一些网络通信。在尝试让接受的套接字接受传入数据几个小时后,我遇到了一个页面,该页面指出要调用CAsyncSocket的OnReceive函数,套接字必须位于主GUI线程的上下文中。将其移动到主GUI线程允许套接字开始接收数据。

我的问题是:有没有人知道这方面的解决方法?套接字之前在GUI线程上,并且OnAccept被称为罚款。接受的套接字可用于发送数据没问题,只是无法接收任何东西。如果可以避免的话,我宁愿不必重新设计这部分软件。

1 个答案:

答案 0 :(得分:3)

简单地为套接字创建一个具有自己的消息队列的单独线程会更简单吗?我不认为需要在主消息队列上创建CAsyncSocket,只需要创建一些消息队列。请参阅CWinThread的文档,了解如何使用自己的MFC兼容消息队列创建单独的线程。

不幸的是,从新线程的上下文中调用所有套接字操作至关重要。 MFC在隐藏类中使用全局状态,这些类使用线程本地存储来保存每线程信息,并且该信息在许多CAsynchSocket方法中使用。这意味着CAsynchSocket具有线程亲和性,您必须始终在任何线程中使用和创建它作为其消息泵。

一种方法是创建CWinThread,在该线程上创建自己的自定义MFC隐藏窗口(通过在该线程的上下文中创建窗口),并在该窗口上为所有套接字操作创建消息和消息处理程序你做的(创造,连接等)。确保线程正在传送消息(“Run()”方法执行此操作)然后将消息发送/发送到您的窗口以控制您的套接字。

另外,请记住,套接字的回调将在与UI或工作线程不同的线程上进行。如果要更新GUI对象,则需要担心竞争条件和可能的GUI线程关联问题。

如果您担心设计影响,只需创建自己的CThreadSafeAsynchSocket代理对象,并通过消息传递到隐藏窗口委托实际实现。您可以使用SendMessage进行阻塞操作,使用PostMessage进行异步操作。如果将构造函数包装在工厂对象中,则可以延迟创建套接字线程直到需要它为止。

我能想到的最后一个问题是,您需要检测所有代理何时消失并关闭线程。您可以使用由CThreadSafeAsynchSocket的构造函数/析构函数管理的全局引用计数来检测何时关闭该线程。即使您关闭主应用程序窗口,未能关闭该主题也会使您的应用程序挂起隐藏窗口。