我们知道Qt以他的signal和slot机制独步天下。但大家在用的时候有没有注意过,signal和slot是异步的,还是同步的呢?为此我问过不少Qt的使用者,有人说是同步的,有人说是异步的,也有人说着要看Qt的当时心情了¥%&*
其实是异步还是同步,是用户决定的。如果大家仔细看过connect函数的介绍就知道,connect最后的有一个参数 Qt::ConnectionType type 他将决定是异步还是同步(具体的类型可以参见帮助)。只不过平常我们使用的时候,他默认成了Qt::AutoConnection。有的兄台看到这里的时候,就会问,啥是Auto模式。其实Auto模式,就是看Qt的心情来决定是异步还是同步。而决定这个心情的就是,sender和receiver的他们分别所处的线程。如果是同一线程则就是同步调用,如果不在同一线程就是异步调用。
但真相果真如此吗?正像青春永驻的柯南君所指出的,真相永远都隐藏在表面之下。
请各位看官思考以下案例:
class A : public QObject
{
friend class B;
Q_OBJECT
public:
A ()
{
connect(this,SIGNAL(signalTest()),this,SLOT(slotTest()), Qt::AutoConnection);
}
............
signals:
void signalTest();
public slots:
void slotTest();
}
如果这时候我在另外一个线程触发signalTest(), 这时候signalTest和slotTest是同步还是异步呢? 根据帮助的说明,在Auto模式下,如果sender和receiver在同一线程里,
应该是同步调用。
但真相却是,他们是异步调用的。
参见Qt代码,
// determine if this connection should be sent immediately or
// put into the event queue
if ((c->connectionType == Qt::AutoConnection
&& (currentThreadData != sender->d_func()->threadData
|| receiver->d_func()->threadData != sender->d_func()->threadData))
|| (c->connectionType == Qt::QueuedConnection)) {
queued_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv);
continue;
} else if (c->connectionType == Qt::BlockingQueuedConnection) {
blocking_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv);
continue;
}
从代码我们可以看出,在Auto模式下,如果当前线程不和sender是同一个线程,即使receiver和sender在同一线程,也将是异步调用。
太凶残了