我有一个Qt gui为QMainWindow
,其QThread
启动另一个类对象的无限循环。
以下是简要代码:
Calculations.h
Class Calculations : public QObject
{
public:
//many functions!
void run();
signals:
void signalResultAvailable();
void signalECUQueryTimePassed();
private:
//many things!
}
和Calculations.cpp
void Calculations::run()
{
while (1)
{
unsigned long loopStart = millis();
//Heavy calculations per second!
unsigned long loopEnd = millis();
if ((loopEnd - loopStart) <= 1000)
{
delay(1000 - (loopEnd - LoopStart));
emit signalResultAvailable;
}
}
}
MainWindow.h
如下:
Class MainWindow : public QMainWindow
{
private slots:
on_button_Pause_clicked();
private:
Calculations cal;
}
MainWindow.cpp
:
MainWindow::MainWIndow() : ui(new Ui::MainWindow), cal()
{
//all the initializations...
QThread *thread_1 = new Qthread;
cal.moveToThread(thread_1);
connect(thread_1, SIGNAL(started()), &cal, SLOT(run()));
thread_1->start();
}
void MainWindow::on_buttonPause_clicked()
{
// I want to put the Thread pause HERE!
}
我希望在GUI上有一个暂停按钮,所以当用户点击它时,暂停qthread(绝对GUI不能冻结!),当用户点击Resume按钮时,它会继续计算。 我也读过this主题,但它没有帮助,因为它使用了我理解的QThread子类。
有人可以帮助我吗?
答案 0 :(得分:3)
您可以使用计时器代替循环使Qthread为您执行循环:
Calculations::Calculations(QObject *parent) :QObject(parent)
{
timerId = startTimer(0);
}
Calculations::pauze(){
killTimer(timerId);
timerId = 0;
}
Calculations.restart(){
timerId = startTimer(0);
}
Calculations::timerEvent(QTimerEvent *event){
//Heavy calculations per second!
emit signalResultAvailable;
}
pauze
和restart
都是连接到各自按钮的clicked
信号的插槽。
如果您希望它每秒只运行一次,那么您可以将1000而不是0传递给startTimer
。
答案 1 :(得分:1)
在paused
和QMutex
上使用QWaitCondition
标记。
// in header
QMutex mutex;
QWaitCondition waitCondition;
// don't forget to false it in constructor
bool paused;
public slots:
// connect this slot to GUI button toggled(bool) signal
void setPaused(enable);
...
// in source
void setPaused(bool enable)
{
mutex.lock();
paused=enable;
if (!paused)
waitCondition.wakeAll();
mutex.unlock();
}
void Calculations::run()
{
while (1)
{
mutex.lock();
if (paused)
{
waitCondition.wait(&mutex);
}
mutex.unlock();
unsigned long loopStart = millis();
//Heavy calculations per second!
unsigned long loopEnd = millis();
if ((loopEnd - loopStart) <= 1000)
{
delay(1000 - (loopEnd - LoopStart));
emit signalResultAvailable;
}
}
}
<强>更新强>
请注意,在您的实现中,您只能在与Qt :: DirectConnection直接连接到信号的插槽中使用signalResultAvailable()。如果你想用Qt :: QueuedConnection将它恢复到主GUI线程,你永远不会得到它。请注意,您在Qt :: DirectConnection中连接的所有内容都在调用者线程中调用,因此您无法在该插槽中更新GUI。
更新2
嗯,还有更多。看看这个结构:
QThread *thread_1 = new Qthread;
cal.moveToThread(thread_1);
connect(thread_1, SIGNAL(started()), &cal, SLOT(run()));
thread_1->start();
我想,您希望在cal.run()
中调用thread_1
方法。对不起,它将在您当前的GUI线程中调用。如果您已将Qt::AutoConnection
声明为公共插槽(可能只是隐藏在void run()
后面),则会在单独的线程中通过//many functions!
调用它。
再次注意。正如我所提到的,run()
中自定义无限循环中发出的信号永远不会转到其他线程。此外,在你的实现中,现在没有办法离开你的线程:QThread::stop()
无济于事,因为它只会停止Qt事件循环(你进入你的循环后你永远不会到达,但顺便说一句)但是它不会破坏您的自定义无限循环中的执行。