2013-02-10 5 views
8

Ich versuche, eine C# Winform-Anwendung, die ZeroMQ (clrzmq. Net-Bindungen (x86) über Nuget) in einem Pub/Sub-Modell verwendet.Beispiele für Zeromq Pub/Sub mit C# Winform

Nach vielen Suchen kann ich nur Standalone C# Beispiele finden, wo der Code eine while-Anweisung verwendet, um neue Nachrichten unbegrenzt zu verarbeiten. Wenn ich versuche, diese Beispiele zu verwenden, weiß ich nicht, wohin ich den Code setzen soll, und er blockiert nur die GUI und alles andere.

Ich weiß nicht, ob es unmöglich ist, ohne einen anderen Thread zu tun, aber ich hatte den Eindruck, dass ZeroMQ asynchronen Verhaltensweisen funktionieren könnte, ohne zusätzliche Threads zu codieren. Vielleicht weiß ich nicht, wo ich den zeromq-Code einfügen soll, oder vielleicht brauche ich wirklich einen anderen Thread.

Wenn jemand ein einfaches Pub/Sub-Beispiel mit Anweisungen bereitstellen könnte, wo der Code tatsächlich in eine standardmäßige C# -Winform-Anwendung eingefügt werden soll, wäre dies sehr zu begrüßen.

Antwort

7

Ich nehme an, dass Sie die clrzmq ZeroMq wrapper in Ihrem Projekt verwenden. Soweit ich weiß, ist es nicht möglich, blockierende Nachrichten in einer einfachen Schleife mit clrzmq zu empfangen, es wird entweder unbegrenzt für eine bestimmte Zeit blockiert (durch Angabe eines Timeouts für die Empfangsmethode) oder bis Sie eine Nachricht erhalten .

Es ist jedoch ziemlich trivial, einen Thread einzurichten, um den Socket regelmäßig abzufragen und eingehende Nachrichten auf eine Queue zu übertragen. Sie können dann zum Beispiel eine einfache WinForms Timer verwenden, um alle anstehenden Nachrichten von dieser (gemeinsam genutzten) Queue periodisch zu entfernen. Hier ist ein funktionierendes Beispiel eines Gewinde Teilnehmer:

public class ZeroMqSubscriber 
{ 
    private readonly ZmqContext _zmqContext; 
    private readonly ZmqSocket _zmqSocket; 
    private readonly Thread _workerThread; 
    private readonly ManualResetEvent _stopEvent = new ManualResetEvent(false); 
    private readonly object _locker = new object(); 
    private readonly Queue<string> _queue = new Queue<string>(); 

    public ZeroMqSubscriber(string endPoint) 
    { 
     _zmqContext = ZmqContext.Create(); 
     _zmqSocket = _zmqContext.CreateSocket(SocketType.SUB); 
     _zmqSocket.Connect(endPoint); 
     _zmqSocket.SubscribeAll(); 

     _workerThread = new Thread(ReceiveData); 
     _workerThread.Start(); 
    } 

    public string[] GetMessages() 
    { 
     lock (_locker) 
     { 
      var messages = _queue.ToArray(); 
      _queue.Clear(); 
      return messages; 
     } 
    } 

    public void Stop() 
    { 
     _stopEvent.Set(); 
     _workerThread.Join(); 
    } 

    private void ReceiveData() 
    { 
     try 
     { 
      while (!_stopEvent.WaitOne(0)) 
      { 
       var message = _zmqSocket.Receive(Encoding.UTF8, 
           new TimeSpan(0, 0, 0, 1)); 
       if (string.IsNullOrEmpty(message)) 
        continue; 

       lock (_locker) 
        _queue.Enqueue(message); 
      } 
     } 
     finally 
     { 
      _zmqSocket.Dispose(); 
      _zmqContext.Dispose(); 
     } 
    } 
} 

Von der Form Sie einfach die Warteschlange regelmäßig abfragen (in diesem Beispiel verwendet ein Forms Timer und einfach anhängt die Nachrichtendaten an einen Textbox):

private readonly ZeroMqSubscriber _zeroMqSubscriber = 
     new ZeroMqSubscriber("tcp://127.0.0.1:5000"); 

void ReceiveTimerTick(object sender, EventArgs e) 
{ 
    var messages = _zeroMqSubscriber.GetMessages(); 
    foreach (var message in messages) 
     _textbox.AppendText(message + Environment.NewLine); 
} 
+0

Wenn Ich versuche, Ihre ZeroMqSubscriber Klasse oben zu verwenden, Visual Studio sagt, dass es den Namespace oder den Namen für "ZmqContext" und einige andere Klasseninstanzen, die Sie verwenden, nicht finden kann. Ja, ich habe "mit ZMQ". Irgendwelche Ideen? – uberdanzik

+0

Verwenden Sie die clrzmq ZeroMq .NET-Bindung? Ich benutze ZeroMQ, nicht ZMQ. Das Beispiel enthält eine Verknüpfung zum clrzmq-Projekt (am Anfang des Posts). Ich bin mir nicht sicher, warum die Beispiele auf der Hauptseite ZMQ sagen, ich denke, das ist der alte Namespace-Name. Die [ZeroMq .NET-Beispiele] (https://github.com/imatix/zguide/tree/master/examples/C%23) verwenden 'using ZeroMQ'. –

+0

Ja, die [neueste clrzmq-Quelle] (https://github.com/zeromq/clrzmq/blob/master/src/ZeroMQ/ZmqContext.cs) verwendet ** ZeroMQ ** als Namespace. –