【发布时间】:2013-04-19 05:11:30
【问题描述】:
考虑下面的示例代码(作为示例,我快速输入它,如果有错误也没关系 - 我对理论感兴趣)。
bool shutDown = false; //global
int main()
{
CreateThread(NULL, 0, &MessengerLoop, NULL, 0, NULL);
//do other programmy stuff...
}
DWORD WINAPI MessengerLoop( LPVOID lpParam )
{
zmq::context_t context(1);
zmq::socket_t socket (context, ZMQ_SUB);
socket.connect("tcp://localhost:5556");
socket.setsockopt(ZMQ_SUBSCRIBE, "10001 ", 6);
while(!shutDown)
{
zmq_msg_t getMessage;
zmq_msg_init(&getMessage);
zmq_msg_recv (&getMessage, socket, 0); //This line will wait forever for a message
processMessage(getMessage);
}
}
创建一个线程来等待传入的消息并适当地处理它们。线程一直在循环,直到 shutDown 设置为 true。
在 ZeroMQ 中,Guide 明确说明了必须清理的内容,即消息、套接字和上下文。
我的问题是:由于recv 将永远等待消息,阻塞线程,如果从未收到消息,我该如何安全地关闭该线程?
【问题讨论】:
-
在
zmq_msg_recv中使用ZMQ_DONTWAIT标志,并在短时间内添加手动Sleep?所以使用更多的轮询方法? -
我不知道 zmg_* API,但是在普通的套接字 API 中,在另一个线程中关闭套接字就足够了,并且 recv 失败退出。为此,您需要连接到另一个线程中的套接字,以使
socket变量可用于关闭。MessengerLoop必须只包含无限的recv循环。 -
@AlexFarber 我曾考虑过这一点,但除非我弄错了,否则不会导致所有消息处理都在同一个 MessengerLoop 线程中完成吗?在这种情况下,我必须设置某种信号系统来区分“我正在等待消息,所以是的,你可以终止我”和“我正忙于处理某些事情,不要终止我”。这似乎比基于轮询的系统更混乱。我对这个网络消息问题很陌生,是我遗漏了什么还是这是正常的做事方式?
-
我不熟悉 zmq_* 函数,但是查看您发布的代码,我认为当套接字关闭时,循环中唯一可能失败的行是
zmq_msg_recv调用。但这只是我的猜测。一旦这个调用失败,退出循环和整个线程。 -
另外,从主线程关闭socket后,需要等待线程句柄,当线程真正退出时——通用Win32多线程编程规则。