2016-03-06 119 views
1

我有这样的代码:为什么互斥已经解锁

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; 
} 

如果我点击calculateBtn同时再次startProcess()有没有完成后,我的程序崩溃了:

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

我99.999%肯定你正在做的事情不会做你想做的。图形用户界面处理程序几乎总是作为一个状态机由ONE THREAD运行。在GUI事件处理程序中,您不得进行任何可能会阻塞任何延长时间间隔的电话(这意味着“人类注意力”)。如果'startProcess();'发出一个线程或threadPooled任务,该任务应该向GUI线程发出完成信号,然后可以重新启用该按钮。你不能等待一个事件处理程序,然后启用按钮。 GUI状态机不像控制台程序,你不能像这样编写它们:) –

+0

看起来像是错误地使用了'mutex'变量。你需要提供更多关于创建和使用这个变量和'startProcess()'定义的信息。 –

+0

@VladimirBershov我修改了我的问题,我尝试添加了一些代码 – Wanksta

回答

0

相同的互斥锁被同一个线程(主线程,包含事件循环)锁定两次,对于non-recursive mutex无效。

但即使是递归互斥体也不能解决您的代码的基本问题;你需要一个标志来表明你已经在进行计算,并在运行时从所有后续调用返回到你的方法,否则你会在同一个线程中多次启动它们,一个中断另一个,可能带来不好的结果。更好的是,在方法运行时禁用按钮,注意不要通过其他方式调用该方法。

但是,如果调用startProcess()多次,同时运行其意,你就必须开始为每个按钮按下和照顾访问一个线程共享数据(使用互斥,最有可能) - 这就是真正的乐趣开始。

+0

我编辑了我的问题。没有共享数据,我只想要一个startProcess()在其他startProcess()完成之前不会启动。 – Wanksta

0

我认为你(默认情况下)有一个Qt :: DirectConnection这个按钮按下,对吧?即:

connect(..., SIGNAL(...), 
     ..., SLOT(:on_calculateBtn_clicked()), <by-default-Qt::DirectConnection>); 

我看到这里的问题是,第一次按下按钮将立即运行功能void MainWindow::on_calculateBtn_clicked() ....这是所有好为止,互斥被锁定,巨大的Calcs(计算)正在运行。

但是,当你再次按下按钮,void MainWindow::on_calculateBtn_clicked()再次立即运行(如中断)。它所做的第一件事是尝试锁定互斥锁,并且它必须挂在这里。

如果您连接到插槽void MainWindow::on_calculateBtn_clicked() Qt :: QueuedConnection,那么它将不会触发按钮按下,直到它清除其任务队列上的其他任务。

但是....天气还是不是你的设计在这里是好是值得商榷的,我想对你应该重新考虑你的策略(如一些评论建议)

编辑

噢,意在添加.....回答你的问题,因此我不认为这个互斥锁已经开始解锁两次了......它只是直接连接的本质

相关问题