[英]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.