Qt那点事儿(一)

标签: qt | 发表时间:2011-08-26 10:41 | 作者:樱桃小锤子 niko
出处:http://www.cppblog.com/

第一回 Signal和Slot是同步的还是异步的?

  我们知道Qt以他的signal和slot机制独步天下。但大家在用的时候有没有注意过,signal和slot之间是异步的,还是同步的呢?为此我问过不少使用Qt的道友。有人说是同步的,有人说是异步的,也有人说要看当时你的人品。:( #$%^&*

  为此贫道,特别做了以下几个测试:

     First,在main()主函数里,设置两个基于QObject为父类的对象a和b,a触发signal,b接受signal。请看具体案例:

    

 1 class MyTestA : public QObject
2 {
3 Q_OBJECT
4 public:
5 void emitSignal()
6 {
7 signalMyTestA();
8 }
9
10 public slots:
11 void slotMyTestA()
12 {
13 qDebug()<<"slotMyTestA is called.";
14 }
15 signals:
16 void signalMyTestA();
17 };
18
19 class MyTestB : public QObject
20 {
21 Q_OBJECT
22 public slots:
23 void slotMyTestB()
24 {
25 qDebug()<<"slotMyTestB is called.";
26 }
27 signals:
28 void signalMyTestB();
29 };
30
31 int main(int argc, char *argv[])
32 {
33 QApplication app(argc, argv);
34
35 MyTestA a;
36 MyTestB b;
37 QObject::connect(&a,SIGNAL(signalMyTestA()),&b,SLOT(slotMyTestB()));
38
39 a.emitSignal();
40
41 return app.exec();
42 }

在slotMyTestB的函数里打个断点,看一下调用堆栈(call stack)。

是同步调用的,某些道友开始拈胡微笑,实践出真知啊。

此时只见东方黑云滚滚,电闪雷鸣,又有道友开始度劫了。突然一度劫道友横眉冷对,拿起拂尘刷刷的改写了上面的代码。只见此道友把a对象挪到了一个新线程中(MyTestC创建的),而b对象仍然在主线程中。然后a对象触发信号。

class MyTestA : public QObject
{
    Q_OBJECT
public:
    void emitSignal()
    {
        signalMyTestA();
    }
public slots:
    void slotMyTestA()
    {
        qDebug()<<"slotMyTestA is called.";
    }
signals:
    void signalMyTestA();
};
class MyTestB : public QObject
{
    Q_OBJECT
public slots:
    void slotMyTestB()
    {
        qDebug()<<"slotMyTestB is called.";
    }
signals:
    void signalMyTestB();
};
extern MyTestB *g_pMyTestB;
class MyTestC : public QThread
{
    Q_OBJECT
public:
    void run()
    {
        MyTestA a;
        connect(&a,SIGNAL(signalMyTestA()),g_pMyTestB,SLOT(slotMyTestB()));
        a.emitSignal();
        exec();
    }
public slots:
    void slotMyTestC()
    {
        qDebug()<<"slotMyTestC is called.";
    }
signals:
    void signalMyTestC();
};
class MyTest : public QDialog
{
    Q_OBJECT
public:
    MyTest(QWidget *parent = 0, Qt::WFlags flags = 0);
    ~MyTest();
private:
    Ui::MyTestClass ui;
};
////////////////////////////////////////////////
MyTestB *g_pMyTestB = NULL;
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MyTestB b;
    g_pMyTestB = &b;
    MyTestC c;
    c.start();
    return app.exec();
}

说时迟,那时快。在一道紫雷劈下之际,按下了F5。只见,此时的调用堆栈显示,

奇迹出现了,居然变成异步调用了。只见东方天空万道金光射下,在阵阵仙乐声中,传来朗朗之声:"贫道尘事已了,再无牵挂"。

难道Qt真的是靠人品的,或者Qt莫不是也是修仙道友,不日也将飞升。

在吾等众人膜拜加疑惑之时,只见飞升前辈,留下一条偈语。内事不决问百度,外事不决问谷歌。

吾等众人立刻搜寻,恍然大物。

原来signal和slot是异步调用还是同步调用,取决于对connect的设定。其实connect还有一个参数(Qt::ConnectionType),是它决定了是同步还是异步。以下是ConnectionType的定义

只不过,平常它有一个默认值Qt::AutoConnection,我们忽略了它。这时有道友问道,为何在AutoConnection模式下,有时是同步,有时是异步,莫非Auto就是人品代名词。

非也,其实Auto是这样规定的,

当sender和receiver在同一线程时,就是同步模式,而在不同线程时,则是异步模式。

众人皆曰善。

就在众人弹冠相庆之时,突然一道类似眼镜发出的寒光闪过,一个黑影渐渐清晰了起来。

他居然就是..................

青春永驻,十二年如一日的柯南君,他招牌式的磁性声音给众道友一晴天霹雳,“诸位以为这就是全部的真相吗?”

接着他刷刷的又改写了代码,在主线程中生成a,b两个对象,而a对象在新线程(MyTestC创建的)中触发信号。

 

class MyTestA : public QObject
{
    Q_OBJECT
public:
    void emitSignal()
    {
        signalMyTestA();
    }
public slots:
    void slotMyTestA()
    {
        qDebug()<<"slotMyTestA is called.";
    }
signals:
    void signalMyTestA();
};
class MyTestB : public QObject
{
    Q_OBJECT
public slots:
    void slotMyTestB()
    {
        qDebug()<<"slotMyTestB is called.";
    }
signals:
    void signalMyTestB();
};
extern MyTestB *g_pMyTestB;
extern MyTestA *g_pMyTestA;
class MyTestC : public QThread
{
    Q_OBJECT
public:
    void run()
    {
        g_pMyTestA->emitSignal();
        exec();
    }
public slots:
    void slotMyTestC()
    {
        qDebug()<<"slotMyTestC is called.";
    }
signals:
    void signalMyTestC();
};
/////////////////////////////////////////////
MyTestB *g_pMyTestB = NULL;
MyTestA *g_pMyTestA = NULL;
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MyTestA a;
    g_pMyTestA = &a;
    MyTestB b;
    g_pMyTestB = &b;
    QObject::connect(&a,SIGNAL(signalMyTestA()),&b,SLOT(slotMyTestB()));
    MyTestC c;
    c.start();
    return app.exec();
}

 

在众人疑惑的眼光中,此君淡定的按下了F5。只见调用堆栈(call stack)显示

众人皆惊呼,“Impossible”。a和b明明是属于一个线程的,为何会异步调用。此时我们熟悉的语录,又在耳边回响,是"我相信真相只有一个!!!"这句话吗?No,只见柯南君,优雅地挥了挥手指,"Nothing impossible",从口中缓缓滑出。

。众人皆扑街,“有屁快放”。

此时柯南君缓缓从口袋中,摸出一张纸,抛向空中,然后转身离去。只见随风飘落的纸面上面摘录了这么一段Qt源代码,在Auto模式下,如果要同步调用,不仅要求sender和receiver是同一线程,而且sender触发的时候,所在的线程也要和receiver一致。

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

摘自qobject.cpp

z众人皆惊,原来在Auto模式下,如果sender的触发时所处的线程和receiver不同,也会是异步调用。此时道友齐声向柯南喊道“这是全部的真相了吗”?柯南转过头来笑而不语,渐渐又消失在黑暗中。“有多少无耻可以重来”漂上了众人的心头。望着远处的雨后阳光,一个大大的问号也出现在众人头顶,"Qt你到底有多无耻???"。众人又陷入了沉思。

欲知后事如何,请听下回分解。

 

此篇已在CNBLOG同时发布

 

 

 

 

 

 






樱桃小锤子 2011-08-26 10:41 发表评论

相关 [qt] 推荐:

Qt Project 上线

- ArmadilloCommander - LinuxTOY
还记得本站先前报道的 Qt 移至开放式管理么. 现在它的 Qt Project 网站正式上线了. 在发布报道中,为了表示 Qt 不再是 Nokia 的一言堂,特别指出了 QtCore 的维护者 Thiago 不是 Nokia 的雇员. Qt Project 主页. 收藏到 del.icio.us |.

Qt——转战Java?

- - 博客 - 伯乐在线
编者按:事实上,在跨平台开发方面,Qt仍是最好的工具之一,无可厚非,但Qt目前没有得到任何主流移动操作系统的正式支持. 诺基亚的未来计划,定位非常模糊,这也是令很多第三方开发者感到失望,因此将导致诺基亚屡遭失败的原因. Qt的主要开发者之一Mirko Boehm在博客上强烈讽刺Nokia裁了Qt部门的决定,称其为“绝望之举”,而非“策略变更”.

Qt ——塞班之死

- - 博客 - 伯乐在线
编者按:显然,关注Qt及nokia生死存亡的开发者还是大有人在,面对褒贬不一的评价,面对各种各样的传闻,倾诉权在自己身上,决定权无法改变. 探讨Qt被裁之后,转念来说说 “Symbian在中国是怎么猝死的. ”最终迫使nokia裁去的Qt会不会也瞬间猝死. nokia的局面是否会被WP扭转. 曾经Symbian在市场中覆盖面很广.

Qt那点事儿(一)

- niko - C++博客-首页原创精华区
第一回 Signal和Slot是同步的还是异步的.   我们知道Qt以他的signal和slot机制独步天下. 但大家在用的时候有没有注意过,signal和slot之间是异步的,还是同步的呢. 有人说是同步的,有人说是异步的,也有人说要看当时你的人品.   为此贫道,特别做了以下几个测试:.      First,在main()主函数里,设置两个基于QObject为父类的对象a和b,a触发signal,b接受signal.

Dijia 从 Nokia 收购 Qt

- - 博客 - 伯乐在线
Nokia在去年三月份将Qt团队外包给了芬兰的一家名叫Digia的公司. 据 国外媒体thenextweb报道,今天Nokia正式将Qt开源软件技术卖给了Digia. 而Digia预计在掌管这个项目后将其推广到Android、iOS和Windows 8 平台. Digia主要目标是借助Qt生态系统加强自身的研发能力,并且将这项技术推广到Android和iOS智能手机平台,也包括了微软的Windows 8系统,之前Nokia就有意在平板上使用Windows 8系统.

N9 + Qt 很给力——看看 N9 的那些 Qt App 们

- Brant - 爱范儿 · Beats of Bits
也许德国,瑞典,美国,日本的诺基亚玩家应该羡慕中国用户,因为我们不久就能买到行货诺基亚 N9 了. 跟两年前的 N900 不同,诺基亚这次非常重视中国市场,并跟第三方应用商展开广泛合作,行货 N9 将会内置非常多的中文应用程序,而且都是基于 Qt 开发的. 诺基亚在 Qt 开发站点上放出了几段视频,向开发者们展示 N9 + Qt 的流畅程度和开发优势.

Qt 将移至开放式管理

- 逸川 - LinuxTOY
在最近举行的 XDC2011 会议上,Nokia 宣布将 Qt 移至开放式管理模式. Qt 将拥有一个独立的域名 qt-project.org (尚未上线),由一个专注于 Qt 的非营利性组织管理. 所有的技术上的决定,包括项目发展方向,将会由包括贡献者、审核者和维护者组成的社区团体共同决定. 预期 qt-project.org 将会在下个月的 Qt 开发者日之前上线.

诺基亚开除QT团队

- - 博客 - 伯乐在线
诺基亚的裁员终于波及到了QT,并不完全出人意料,在其开发平台“战略性转移”后,这只是一个时间问题. 在诺基亚计划解雇的1万名雇员中,有700位开发者, 其中100位是QT核心开发者( 快照). 诺基亚是QT开源项目的 最主要资助者,Mirko Boehm 说,QT 的核心成员就100人. 因此诺基亚事实上是解雇了整个QT团队.

嵌入式Linux冷启动一秒进入QT

- 王雪松 - Solidot
一位嵌入式系统开发者在博客上演示了在一台嵌入式Linux设备上冷启动载入一个QT应用程序,整个过程仅仅只需一秒钟. 冷启动中用的组件包括了UBoot(2009-01),Linux kernel(2.6.31-rc7)和Qt Embedded Open Source 4.6.2. 他还公开了一份幻灯片文档,介绍了修改方法,如何减少启动时间.

跨平台开发工具Qt SDK 1.1.3发布

- tinda - Solidot
chinakr 写道 "Nokia于本月1日发布了Qt SDK 1.1.3,更新内容包括功能改进和软件质量提升. Qt SDK 1.1.3下载链接:Windows版,Linux版(32位),Linux版(64位)和Mac OS X版.