2011-11-05 35 views
5

Sử dụng một ổ cắm nhắn tin ZMQ.SocketType.REP (trả lời) với ZeroMQ, tôi nhận được tin nhắn và sau đó gửi lại tin nhắn "OK".Ổ cắm ZeroMQ Recv() ném 'Bối cảnh đã bị chấm dứt' ngoại lệ - tại sao và cách khôi phục?

Hiện tại, tôi đang thử địa phương này (gửi/nhận tin nhắn từ cùng một ứng dụng giao diện điều khiển C# chạy trên cùng một máy).

Khá thường xuyên (sau khoảng 1500 tin nhắn), các dòng:

var receivedBytes = _recvSocket.Recv();

... sẽ ném một ngoại lệ: Context was terminated

Câu hỏi của tôi là, tại sao điều này xảy ra, và làm thế nào để bạn phục hồi từ nó?

Tôi có một System.Threading.Thread chuyên dụng để chạy của tôi "server-side" ZeroMQ reply ổ cắm, đây là vòng lặp mà nó chạy:

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); 
      } 
     } 
    } 

Trả lời

7

Nó có nghĩa là một người nào đó (các bộ thu rác?) Đã đóng bối cảnh .

+0

Bạn đã chính xác - ngữ cảnh được thiết lập theo cách mà GC can thiệp vào nó. Cảm ơn bạn!! – Brandon

+0

Bạn có thể giải thích về điều này không? – Sergejus

+0

Một cách khác là sử dụng 'GC.KeepAlive': http://msdn.microsoft.com/en-us/library/system.gc.keepalive(v=vs.90).aspx để ngăn chặn việc thu thập rác trên đối tượng. –

0

Thêm câu trả lời này cho đầy đủ.

if (_zmqc == null) 
    { 
     _zmqc = new ZMQ.Context(1); 
    } 
    _recvSocket = _zmqc.Socket(ZMQ.SocketType.REP); 

Đây là nơi duy nhất _zmqc bối cảnh được sử dụng. Do đó GC thấy nó như là một ứng cử viên tiềm năng để làm sạch. Một khi nó được, vứt bỏ được gọi vào nó. Điều này sau đó sẽ buộc tất cả các ổ cắm phải kết thúc bằng một số lỗi ETERM từ ZMQ.

Điều đầu tiên cần được thực hiện là sử dụng mệnh đề sử dụng xung quanh nơi ngữ cảnh cần để sống. Điều này sẽ buộc GC rời khỏi đối tượng một mình.

Tiếp theo khi đóng vòng lặp, bạn cần phải nắm bắt ngoại lệ thấy rằng số lỗi ETERM của nó và sau đó thoát ra một cách duyên dáng.

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 
    } 
} 

Tận hưởng!

Chỉnh sửa: Hầu hết số lỗi bị quên trong ZMQ là "ưa thích" số đầu tiên bắt đầu tại 156384712 và chúng tăng lên. ETERM là 156384712 + 53. Tuy nhiên, chỉ cần doco vì điều này có thể đã thay đổi kể từ khi viết.

Các vấn đề liên quan