我有这段代码:
mainwindow.h:
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow {
private:
QMutex mutex;
}
mainwindow.cpp:
void MainWindow::on_calculateBtn_clicked() {
QMutexLocker locker(&mutex);
qDebug() << "mutex has been locked" << endl;
ui->calculateBtn->setEnabled(false);
startProcess(); // huge calcutations
ui->calculateBtn->setEnabled(true); // performed before startProcess() has finished (why?)
qDebug() << "mutex will be unlocked" << endl;
}
如果我在startProcess()尚未完成时再次单击calculateBtn,我的程序崩溃了:
pure virtual method called
The program has unexpectedly finished.
我试过了:
void MainWindow::on_calculateBtn_clicked() {
if (!processing) {
processing = true;
ui->calculateBtn->setEnabled(false);
startProcess();
ui->calculateBtn->setEnabled(true); // performed before startProcess() has finished (why?)
processing = false;
}
}
没有共享数据,我只想在其他startProcess()完成之前不会启动一个startProcess()。 为什么会这样?我认为互斥锁必须在on_calculateBtn_clicked()中锁定函数startProcess(),并且不会发生任何事情。看来我不知道任何重要的事情。提前感谢任何建议。
答案 0 :(得分:0)
相同的互斥锁从同一个线程(包含事件循环的主线程)被锁定两次,这对non-recursive mutex无效。
但即使是递归的互斥锁也无法解决代码的基本问题;你需要一个标志来表明你已经在进行计算,并在运行时从你对方法的所有后续调用返回,否则你将在同一个线程中多次启动它们,一个中断另一个,可能是糟糕的结果。更方便的是,在方法运行时禁用按钮并注意不要通过其他方式调用。
但是,如果多次调用startProcess()
并同时运行它,则必须为每个按键启动一个线程,并注意以访问共享数据(最常见的是使用互斥体) - 这真正的乐趣开始了。
答案 1 :(得分:0)
我认为你(默认情况下)按下这个按钮就有一个Qt :: DirectConnection,对吗?即:
connect(..., SIGNAL(...),
..., SLOT(:on_calculateBtn_clicked()), <by-default-Qt::DirectConnection>);
我在这里看到的问题是按下第一个按钮会立即运行函数void MainWindow::on_calculateBtn_clicked()
....到目前为止,这是好的,互斥锁被锁定并且正在运行大量计算。
然而,当您再次按下按钮时,void MainWindow::on_calculateBtn_clicked()
将再次立即运行(如中断)。它首先要做的是尝试锁定互斥锁,它必须挂在这里。
如果您连接到插槽void MainWindow::on_calculateBtn_clicked()
Qt :: QueuedConnection,则它不会触发按钮按下,直到它清除其任务队列中的其他任务为止。
但....天气与否你的设计在这里很好是值得怀疑的,我想你应该重新思考你的策略(正如一些评论所暗示的那样)
修改强>
哦,是的,意味着要添加.....来回答你的问题,因此我不认为互斥锁开始被解锁两次......它只是直接连接的本质