这是QThread子类的run方法:
void crono::Controller::run() {
//initialise timer
int *i = & this->model->seconds_elapsed;
for (*i = 0; *i < this->model->seconds_total; (*i)++) {
//calculate current seconds/minutes/hours elapsed starting from seconds_elapsed (*i)
this->model->tick();
//should display in the form the time elapsed
this->vista->showTime();
sleep(1000);
}
Beep(1000, 500); //beep when all is over
}
控制器更新模型值。
QT表单在启动时打开,我猜在主应用程序线程中。
问题是对debug * i = 0和seconds_total = X&gt;的鄙视0,循环只执行一次,在第一次调试停止后(它没有结束),表格弹出但没有任何反应。
我唯一可以猜到的是,Controller Thread失去了优先级,再也没有获得cpu。
如何避免这种情况?
修改 的 我正在尝试使用QTimer,运气不好。
我将更新声明为公共插槽,然后实现如下:
void crono::Controller::update() {
this->modello->tick();
this->vista->showTime();
//eventually stop at some point (pointer to timer and timer->stop()?
//...
//Beep(1000, 500);
}
我将QTimer插入控制器(线程)对象而不是循环周期:
void crono::Controller::run() {
//inizializzo timer
int *i = & this->modello->secondi_trascorsi;
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()),this, SLOT(update()));
timer->start(1000);
}
我不知道为什么,但是从不调用update()方法,而是被无限次调用。为什么呢?
答案 0 :(得分:5)
常见的混淆是QThread
在自己独立的线程中运行。不是这种情况;相反,QThread
在它控制的子线程中启动一个事件循环。可以轻松地将QThread
称为QThreadManager
。
简而言之,不要继承QThread
,因为您创建的功能驻留在主线程中(而不是QThread
处理的线程)。创建一个QObject子类,其中一个插槽连接到started()
信号。然后使用moveToThread()
并在run()
个实例上调用QThread
。
此外,您无法直接从子线程调用主线程函数。您需要一个排队的连接信号到主线程中的对象以显示对话框。
答案 1 :(得分:3)
正如Tim Meyer在他的评论中指出的那样,你需要在QThread:exec()
实现结束时调用QThread::run()
,这是为了启动线程的事件循环,这是为了工作的信号/插槽机制。
然而,它似乎是you're doing it wrong。
答案 2 :(得分:2)
首先,QThread
几乎不应该被遗传。
线程通常会像在那里描述的那样完成:http://qt-project.org/doc/qt-4.8/QThread.html#details
如果您只是需要线程计算一段时间并在一段时间后执行操作,可能您可以使用QTimer
代替并将QTimer::timeout()
信号连接到您的插槽以显示已用时间。
答案 3 :(得分:1)
我确定你的循环应该是这样的:
//initialize timer
int elapsed = this->model->seconds_elapsed;
for (int i = 0; i < elapsed; i++)
我认为没有必要使用指针。保持简单。
如果这仍然不起作用,那么你做错了其他事情,而且你的代码并不明显。
此外,使用sleep
未完成线程信令。您应该查看线程事件,如信号量或条件变量,以用于线程信号。
如果您想定期更新值,为什么不使用QTimer?
sleep
只有非常少的有效用途,我确信你正在解决一个不需要睡眠的问题。