以下是 Qt 信号/插槽连接的工作原理:
注意:使用该类型连接同一个线程中的对象会导致死锁。
还有一个实际上是默认的:Auto Connection如果信号在接收对象具有关联的线程中发出,则行为与直接连接相同。否则,行为与排队连接相同。”
在大多数情况下,默认值按预期工作得很好:
但是,当从线程发出信号时,您有两种选择来处理它:“排队”或“阻塞排队”连接。
为什么没有这样的模式:
因为,正如文档中提到的,使用 Blocking Queued Connection在同一个线程中会导致死锁......所以处理起来真的很痛苦,我经常不得不在我的代码中创建和管理两个信号和连接来处理:
class A
{
Q_OBJECT
public:
A()
{
connect( this, SIGNAL(changedFromThread()), this, SLOT(update()), Qt::BlockingQueuedConnection );
connect( this, SIGNAL(changedNotFromThread()), this, SLOT(update()) );
}
void notifySomethingChanged()
{
if ( QObject().thread() != thread() )
emit changedFromThread(); // would dead-lock if in same thread
else
emit changedNotFromThread();
}
public slots:
void update()
{
// Do some changes to A that cannot be done from a worker thread
}
signals:
void changedFromThread();
void changedNotFromThread();
};
如果这样的模式(我们称之为
Qt::AutoBlockingConnection
可用),我可以写:class A
{
Q_OBJECT
public:
A()
{
connect( this, SIGNAL(changedFromThread()), this, SLOT(update()), Qt::AutoBlockingConnection );
}
void notifySomethingChanged()
{
emit changedFromThread(); // would dead-lock if in same thread
}
public slots:
void update()
{
// Do some changes to A that cannot be done from a worker thread
}
signals:
void changedFromThread();
};
为什么只提供线程友好的连接以在
Qt::DirectConnection
之间进行交换有什么好的理由吗?和 Qt::QueuedConnection
但没有在 Qt::DirectConnection
之间交换和 Qt::BlockingQueuedConnection
?
最佳答案
我猜 Qt 开发团队根本不希望您指定连接类型。
我可以理解这种设计,从某种意义上说,故意阻塞几乎总是应该避免的,如果你阻塞 UI 线程,更是如此。
如果您想同步 2 QObject
生活在不同的线程中,在它们中使用信号和槽,并相应地连接它们。
但是,如果您处于主从方案(通常 QMainWindow
拥有 QObject
和 QObject::moveToThread(new QThread)
),您可以:
QObject
的信号进入您的 QMainWindow
QObject
插槽使用 QMetaObject::invokeMethod
进入QMainWindow
,所以方法调用被异步处理QObject
线。 关于multithreading - 为什么没有 Qt 连接模式在 Qt::DirectConnection 和 Qt::BlockingQueuedConnection 之间自动选择?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46280830/