以下是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
之间无交换,是否有任何正当理由?
答案 0 :(得分:0)
我猜想Qt开发团队根本不希望您指定连接类型。 我可以理解这种设计,从某种意义上说,几乎应该避免故意阻止,如果要阻止UI线程,则更应避免。
如果您希望同步生活在不同线程中的2 QObject
,请在它们两个中使用信号和插槽,并进行相应连接。
但是,如果您处于主从场景(通常QMainWindow
和QObject
一起拥有QObject::moveToThread(new QThread)
),则可以:
QObject
到您的QMainWindow
的信号QObject
呼叫QMetaObject::invokeMethod
插槽
QMainWindow
,因此方法调用由异步处理
QObject
线程。