ZeroMQ socket Recv()抛出'异常-为什么以及如何恢复
本文关键字:为什么 何恢复 恢复 Recv socket 抛出 ZeroMQ 异常 | 更新日期: 2023-09-27 18:13:33
使用带有ZeroMQ的ZMQ.SocketType.REP
(reply)消息套接字,我正在接收消息,然后发送一个"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);
这是唯一使用context _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。然而,就像这篇文章写的那样,可能已经改变了。