在ZeroMQ上使用ZMQ.SocketType.REP
(回复)消息传递套接字,我正在接收消息,然后发回“OK”消息。
目前,我正在本地尝试(从同一台机器上运行的同一个C#控制台应用程序发送/接收消息)。
相当经常(在大约1500条消息之后),行:
var receivedBytes = _recvSocket.Recv();
...将抛出异常:Context was terminated
我的问题是,为什么会发生这种情况,你如何从中恢复??
我有System.Threading.Thread
致力于运行我的“服务器端”ZeroMQ回复套接字,这是它运行的循环:
private static void MessagingLoopReceive(object state)
{
if (_zmqc == null)
{
_zmqc = new ZMQ.Context(1);
}
_recvSocket = _zmqc.Socket(ZMQ.SocketType.REP);
_recvSocket.Bind("tcp://*:5556");
while (true)
{
if (_queueStop)
{
break;
}
//Console.WriteLine("Server blocking for receive...");
var receivedBytes = _recvSocket.Recv();
if (receivedBytes != null && receivedBytes.Length > 0)
{
//Console.WriteLine("Server message received from client, sending OK");
_recvSocket.Send("OK", Encoding.ASCII);
//Console.WriteLine("Server OK sent, adding message to queue");
_queuedMessages.Enqueue(receivedBytes);
}
else
{
Thread.Sleep(1);
}
}
}
答案 0 :(得分:7)
这意味着有人(垃圾收集器?)关闭了上下文。
答案 1 :(得分:0)
为完整性添加此答案。
if (_zmqc == null)
{
_zmqc = new ZMQ.Context(1);
}
_recvSocket = _zmqc.Socket(ZMQ.SocketType.REP);
这是使用上下文_zmqc的唯一位置。因此,GC认为它是清理的潜在候选人。一旦它,就会调用dispose。然后,这将强制所有套接字以ZMQ中的ETERM错误号终止。
首先需要做的是在上下文需要保持活动的地方使用using子句。这将强制GC单独留下对象。
接下来,当关闭循环时,你需要捕获异常,看看它是一个ETERM错误号,然后正常退出。
try
{
//Any ZMQ socket sending or receiving
}
catch (Exception e)
{
if (e.Errno == ETERM)
{
//Catch a termination error.
break; // or return, or end your loop
}
}
享受!
编辑: 几乎忘了ZMQ中的错误号码是"花哨的"第一个从156384712开始,然后它们上升。 ETERM是156384712 + 53.然而,自从写作以来,这可能已经改变了。