[英]ZeroMQ socket Recv() throws 'Context was terminated' exception - why and how to recover?
使用带有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);
}
}
}
这意味着有人(垃圾收集器?)关闭了上下文。
添加此答案是为了完整性。
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.然而,自从写作以来,这可能已经改变了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.