最近,我用的是NetMQ发送或服务器和客户机之间的接收消息。服务器代码,如:
void Main()
{
CreatePullAndPushSocket();
Task.Factory.StartNew(()=> {
while (true)
{
Thread.Sleep(1);
if (Pull != null)
{
var message = Pull.ReceiveFrameString();
}
}
});
}
PullSocket Pull;
PushSocket Push;
private void CreatePullAndPushSocket()
{
Pull = new PullSocket("tcp://ip1:port1");
Push = new PushSocket("tcp://ip2:port2");
}
public void SendMessageToClient(string message)
{
if (Push != null)
{
Push.SendFrame(message);
}
}
客户端代码,如:
void Main()
{
new Thread(()=> {
while (true)
{
Thread.Sleep(1);
if (Pull != null)
{
var message = Pull.ReceiveFrameString();
}
}
}).Start();
}
PullSocket Pull;
PushSocket Push;
private void CreatePullAndPushSocket()
{
Pull = new PullSocket("tcp://ip2:port2");
Push = new PushSocket("tcp://ip1:port1");
}
public void SendMessageToClient(string message)
{
if (Push != null)
{
Push.SendFrame(message);
}
}
当我运行两个应用程序,这是服务器应用程序,另一个是客户端应用程序。
太奇怪了,我也跟着指导https://netmq.readthedocs.io/en/latest/push-pull/!
在NetMQ很重要的一点就是线程模型。真正重要的是,在多线程,则不应使用套接字。所以,如果线程#1创建的套接字比它应该使用它。如果您想从其他线程发送消息(可以说线程#2)使用相同的插座就忘了这件事。您应该以某种方式从线程#2发送messgae主题#1,那么就应该槽插口发送到客户端。
所以basicly CreatePullAndPushSocket是错误的,奇怪的事情能够比happend。你是在一个线程创建套接字和使用等。它完全错误的。
另一件事是你的Thread.Sleep。你不应该使用的Thread.Sleep,因为你的线程休眠1秒,然后一次检查插座,比睡眠和检查一次。 NetMQ具有功能TryReceive,有超时。因此,它可以检查插座1秒钟,退出来检查,如果你打电话取消/停止或别的什么东西。甚至更好的是有轮询,这将套接字听所有的时间,让我们从其他线程调用停止。
让我们看看下面的代码:
private Poller _poller;
public void Start()
{
Task.Factory.StartNew(()=> {
using(var pullSocket = new PullSocket("tcp://ip1:port1"))
using(_poller = new Poller())
{
pullSocket.ReceiveReady += (object sender, NetMQSocketEventArgsnetMqSocketEventArgs) =>
{
var message = netMqSocketEventArgs.Socket.ReceiveMultipartMessage();
}
_poller.Add(pullSocket);
_poller.Run();
}
});
}
public void Stop()
{
_poller?.Stop();
}
或者,如果你想使用的代码,而与while循环轮询:
私人只读CancellationTokenSource _cts;
public void Start()
{
_cts = new CancellationTokenSource();
var token = _cts.Token;
Task.Factory.StartNew(()=> {
using(var pullSocket = new PullSocket("tcp://ip1:port1"))
{
while (cancellationToken.IsCancellationRequested == false)
{
NetMQMessage message = new NetMQMessage();
bool success = workerSocket.TryReceiveMultipartMessage(TimeSpan.FromSeconds(5), ref message);
if (success == false)
{
continue;
}
//if You reach this line, than You have a message
}
}
},
token,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
}
public void Stop()
{
_cts.Cancel();
_cts.Token.WaitHandle.WaitOne();//if You want wait until service will stop
}
所以回到你的问题,你应该在您创建它使用套接字只能从它的线程内。好东西是要在using语句总是释放它最后总是用插座。
我不能看到SendMessageToClient方法的用法,但我认为你是从一些按钮或东西调用它。你可以做,如果一个插座的构造函数从该线程调用。如果你能告诉我你在哪里调用这个方法我可以谈谈这个。