使用C#winform的zeromq pub / sub示例
我正在尝试创建一个C#Winform应用程序,它在pub / sub模型中使用ZeroMQ(通过nuget的clrzmq .net bindings(x86))。
经过多次搜索,我只能找到独立的C#示例,其中代码使用while语句无限期地处理新消息。 当我尝试使用这些示例时,我不知道将代码放在何处,它只会阻止gui和其他所有内容。
我不知道如果不使用另一个线程是不可能做到的,但我的印象是ZeroMQ的异步行为可以在不编写额外线程的情况下工作。 也许我只是不知道在哪里放zeromq代码,或者我真的需要另一个线程。
如果有人可以提供一个简单的pub / sub示例,其中包含将代码实际插入默认C#winform应用程序的方向,我们将非常感激。
我假设您在项目中使用clrzmq ZeroMq包装器 。 据我所知,使用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 _queue = new Queue (); 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); }
- System.Windows.Forms.Timer是否在与UI不同的线程上运行?
- 用于.NET的强大DateTime解析器库
- 类型’System.Int32’的表达式不能用于方法’Boolean Equals(System.Object)’的’System.Object’类型的参数
- 如何将标签的字体颜色设置为与GroupBox的标题颜色相同?
- 为什么C#编译器会生成方法调用以在IL中调用BaseClass方法
- Null条件运算符评估bool不bool? 正如所料
- 为IList优化LINQ
- 异步添加到ObservableCollection(或替代)
- 在EF4中更改db表名称(entity framework4)