我正在使用ZeroMQ创建项目。我需要启动和杀死线程的函数。启动功能似乎工作正常,但停止功能存在问题。
private Thread _workerThread;
private object _locker = new object();
private bool _stop = false;
public void Start()
{
_workerThread = new Thread(RunZeroMqServer);
_workerThread.Start();
}
public void Stop()
{
lock (_locker)
{
_stop = true;
}
_workerThread.Join();
Console.WriteLine(_workerThread.ThreadState);
}
private void RunZeroMqServer()
{
using (var context = ZmqContext.Create())
using (ZmqSocket server = context.CreateSocket(SocketType.REP))
{
/*
var bindingAddress = new StringBuilder("tcp://");
bindingAddress.Append(_ipAddress);
bindingAddress.Append(":");
bindingAddress.Append(_port);
server.Bind(bindingAddress.ToString());
*/
//server.Bind("tcp://192.168.0.102:50000");
server.Bind("tcp://*:12345");
while (!_stop)
{
string message = server.Receive(Encoding.Unicode);
if (message == null) continue;
var response = ProcessMessage(message);
server.Send(response, Encoding.Unicode);
Thread.Sleep(100);
}
}
}
也许有人对这个Stop()函数有任何想法,为什么它不会杀死线程? 我得到提示我应该使用Thread.MemoryBarrier和volatile但不知道它应该如何工作。 还有ProcessMessage()函数来处理消息,我只是没有将它复制到不乱丢垃圾:)
答案 0 :(得分:1)
问题似乎是您正在调用ZmqSocket.Receive
的阻止版本。在等待接收消息时,它不会处理剩余的代码,因此它永远不会遇到循环条件。
解决方案是使用其中一种非阻塞方法,或使用一种超时方法。试试这个:
string message = server.Receive(Encoding.Unicode, TimeSpan.FromMilliseconds(100));
如果没有收到消息,则应在100ms后返回,如果消息到达,则应在更早时间返回。无论哪种方式,它都会在循环条件下得到一个镜头。
关于_stop
标志本身......
当您从多个线程访问变量时,锁定是个好主意。然而,在简单标志的情况下,读取和写入都是原子操作。在这种情况下,将它声明为volatile(private volatile bool _stop = false;
)就足以告诉编译器确保每次告诉它时它总是实际读取当前值。