我有一些粗略的代码,我一直在尝试:
someserver.cpp(GUI)
#include "server.h"
#include "ui_server.h"
Server::Server(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Server)
{
ui->setupUi(this);
}
Server::~Server()
{
delete ui;
}
void Server::onBtnStartClicked()
{
QThread worker;
worker.start(); // Start worker thread that goes into an infinite loop with a blocking call
}
void Server::onBtnExitClicked()
{
// How do I cleanly stop worker from running?
QApplication::quit();
}
worker.cpp
#include "worker.h"
Worker::Worker(QObject *parent) :
QThread(parent)
{
}
void Worker::run()
{
for (;;)
{
// a blocking IO call here like pipe, or msgrcv
// process data received
}
}
由于工作线程在带有阻塞IO调用的永久循环中运行,我将如何构造它以便在GUI线程中按下“停止”按钮时,工作线程会干净地停止?
答案 0 :(得分:4)
当然,你可以在每次迭代检查Worker::run()
中的for循环中放置一个布尔值,该值在== true时中断并由gui Stop按钮设置。当然,这不会在执行被阻止时退出线程。
可能更好的是摆脱for
循环并使用Qt的信号和插槽来设置回调函数,连接到像QIODevice::readyRead()
这样的信号。只有在套接字/管道中有可用信息时才会调用它们。任何其他时间你都可以使用QThread::exit()
退出该帖子。您还需要在某个时刻调用QThread::exec()
以使事件循环继续。
答案 1 :(得分:0)
首先,您应该设置Worker
的父级,使其成为另一个QObject
的子级,以便在应用完成后正确清理它,并且在堆上创建它。即动态的方式。
第二,最简单的方法就是定义插槽,它将设置Worker
对象的布尔成员并在每个循环中检查它以打破无限循环。不要忘记将此插槽连接到正确的信号。
所以你可以在行中放置Server
的构造函数
QThread * worker = new QThread (this);
connect (this, SIGNAL(terminator()), worker, SLOT(terminate()));
在Server
类声明中:
signals:
terminator();
课程Worker
中的:
private:
bool terminate_; // don't forget initialize it to false
public slots:
void terminate(){terminate_ = true;}
并在周期中:
if (terminate_) {/* .. do exit things...*/; return;
之后,只要您需要,就从服务器发出信号terminator()
。
如果您需要更复杂的管理,那么简单停止,您可能需要使用互斥锁保护您的状态变量。
答案 2 :(得分:0)
要停止工作线程,必须添加“stop requested”布尔标志,该标志应在每次迭代开始时进行测试。此外,还需要同步来读取/写入此布尔标志的值。
这是草稿版本:
class Worker : public QThread {
public:
Worker() : stopRequested(false) {}
void requestStop()
{
QMutexLocker locker(&mutex);
stopRequested = true;
}
void run()
{
forever
{
if (stopRequested())
break;
// a blocking IO call here like pipe, or msgrcv
// process data received
}
}
private:
bool stopRequested()
{
QMutexLocker locker(&mutex);
return stopRequested;
}
QMutex mutex;
bool stopRequested;
};
答案 3 :(得分:0)
Here我认为你解释了你的问题。当您的申请结束时,您应该这样做:
MyClass::~MyClass()
{
m_thread->requestStop();
m_thread->wait(); // Force the thread trying to destroy
// an object of type MyClass, to wait
// the end of the execution of m_thread
delete m_thread;
}
wait()是您的同步问题的解决方案。您也可以将requestStop()
更改为:
void requestStop()
{
mutex.lock();
stopRequested = true;
mutex.unlock();
wait();
}
删除QMutexLocker
对于避免死锁情况非常重要。