2011-11-05 17 views
5

ZMQ.SocketType.REP(返信)メッセージングソケットをZeroMQで使用すると、メッセージを受信して​​「OK」メッセージを戻しています。ZeroMQソケットRecv()は 'コンテキストが終了しました'例外をスローします - なぜ回復するのか?

今のところ、私はこれをローカル(同じマシン上で実行されている同じC#コンソールアプリからのメッセージの送受信)しようとしています。

かなり定期的(約1500メッセージの後に)、ライン:

var receivedBytes = _recvSocket.Recv();

は...例外がスローされます:Context was terminated

私の質問は、これはが起こるない理由で、 あなたはそれからどのように回復しますか?私は、「サーバー側」ZeroMQを実行専用System.Threading.Threadはここで、ソケットを返信してい

は、それが動作することをループです:

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

答えて

7

それは誰か(?ガベージコレクタ)はコンテキストを閉じていることを意味し。

+0

正しいです - GCが干渉しているようにコンテキストが設定されていました。ありがとうございました!! – Brandon

+0

これについて詳しく教えていただけますか? – Sergejus

+0

代わりに、GC.KeepAliveをhttp://msdn.microsoft.com/en-us/library/system.gc.keepalive(v=vs.90).aspxを使用してオブジェクトのガベージコレクションを防ぐこともできます。 –

0

完全性のためにこの回答を追加してください。

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

これはコンテキスト_zmqcが使用される唯一の場所です。したがって、GCは、それをクリーンアップの潜在的候補とみなします。それが終わったら、処分が呼び出されます。これにより、すべてのソケットが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です。しかし、これと同じドコだけが書いてから変更されているかもしれません。

関連する問題