2013-02-10 14 views
8

我正嘗試在pub/sub模型中創建一個使用ZeroMQ(clrzmq .net bindings(x86)via nuget)的C#Winform應用程序。用C#winform創建zeromq pub/sub的示例

經過大量搜索之後,我只能找到獨立的C#示例,其中的代碼使用while語句無限期處理新消息。當我嘗試使用這些示例時,我不知道該把代碼放在哪裏,它只是阻止了gui和其他一切。

我不知道如果不使用另一個線程是不可能的,但我的印象是ZeroMQ的異步行爲可以工作,無需編寫額外的線程。也許我只是不知道在哪裏放置zeromq代碼,或者我確實需要另一個線程。

如果有人可以提供一個簡單的pub/sub示例,其中包含實際將代碼插入默認C#winform應用程序的方向,那麼將非常感激。

回答

7

我假設您在您的項目中使用了clrzmq ZeroMq wrapper。據我所知,在使用clrzmq的簡單循環中無法接收非阻塞消息,它將無限期地阻塞,在特定的時間量內(通過向接收方法提供超時)或直到您收到消息。

但是,設置線程以定期輪詢套接字並將傳入消息推送到Queue上相當簡單。然後,您可以使用一個簡單的WinForms Timer來定期從該(共享)Queue出列任何未決消息。這裏是一個帶螺紋的訂戶的一個工作示例:

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

Form你只是週期性地輪詢隊列(該示例中使用了Forms Timer和簡單地追加所述消息數據到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

當我嘗試使用上面的ZeroMqSubscriber類,Visual Studio說它找不到「ZmqContext」和您使用的其他一些類實例的名稱空間或名稱。是的,我有「使用ZMQ」。有任何想法嗎? – uberdanzik 2013-02-11 18:53:41

+0

您是否使用clrzmq ZeroMq .NET綁定?我有'使用ZeroMQ',而不是ZMQ。該示例包含一個指向clrzmq項目的鏈接(在文章的開頭)。我不知道爲什麼主頁上的示例說ZMQ,我認爲這是舊的命名空間名稱。 [ZeroMq .NET示例](https://github.com/imatix/zguide/tree/master/examples/C%23)使用'使用ZeroMQ'。 – 2013-02-11 20:42:33

+0

是的,[最新的clrzmq源代碼](https://github.com/zeromq/clrzmq/blob/master/src/ZeroMQ/ZmqContext.cs)使用** ZeroMQ **作爲命名空間。 – 2013-02-11 20:49:44