【发布时间】:2019-01-16 02:16:39
【问题描述】:
在以下代码中,我遇到了someOperation 中的死锁:
class A : public QObject {
Q_OBJECT
public:
explicit A(QObject* parent) : QObject(parent), data(0) {}
public slots:
void slot1() {
someOperation();
}
void slot2() {
someOperation();
}
void slot3() {
someOperation();
}
private:
void someOperation() {
QMutexLocker lk(&mutex);
data++;
QMessageBox::warning(NULL, "warning", "warning");
data--;
assert(data == 0);
}
int data;
QMutex mutex; //protect data
};
class Worker: public QThread {
Q_OBJECT
public:
explicit Worker(QObject* parent) : QThread(parent) {}
protected:
virtual void run() {
// some complicated data processing
emit signal1();
// other complicated data processing
emit signal2();
// much complicated data processing
emit signal3();
qDebug() << "end run";
}
signals:
void signal1();
void signal2();
void signal3();
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
A* a = new A(&app);
Worker* w = new Worker(a);
QObject::connect(w, SIGNAL(signal1()), a, SLOT(slot1()), Qt::QueuedConnection);
QObject::connect(w, SIGNAL(signal2()), a, SLOT(slot2()), Qt::QueuedConnection);
QObject::connect(w, SIGNAL(signal3()), a, SLOT(slot3()), Qt::QueuedConnection);
w->start();
return app.exec();
}
有一个线程会发出三个信号,它们都排队连接到A类的一个实例,并且所有A类的槽都会调用someOperation,someOperation被互斥锁保护,它会弹出一个消息框。
Qt::QueuedConnection 2 当控制返回到接收者线程的事件循环时调用槽。该槽在接收者的线程中执行。
当 slot1 的消息框在主线程中仍在执行模式时,似乎调用了 slot2,但当时 slot1 已锁定 mutex,所以死锁。
如何修改代码避免死锁?
更新:(2019 年 1 月 17 日)
我想要存档的是:在 slot1 完成之前不能执行 slot2。
应该保留的有:
- worker是后台线程处理数据,耗时较长;所以,无论如何,这三个信号将从其他线程发出。
- worker 不应通过发出信号来阻塞。
- slots 应该在主线程中执行,因为它们会更新 GUI。
-
someOperation不可重入。
【问题讨论】:
-
我会考虑是否可以在需要查询用户的代码行将后台操作分成两个槽。然后你会在前半部分结束时发出一个信号,这将在 GUI 线程中触发一个消息框对话框,你可以简单地将函数的后半部分连接到对话框的完成信号。
标签: qt qthread qtconcurrent