Qt多个槽被触发,怎么处理??

weixin_38048973 2019-09-19 12:14:06
如题,当一个槽正在执行并且还没执行结束,这时其他事件又触发另一个槽会出现什么结果,后来的这个信号所触发的这个槽的执行会阻塞吗(单线程)
...全文
390 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_38065208 2019-09-19
  • 打赏
  • 举报
回复
楼上 的回复不正确的,请不要误导楼主可好多个信号连接相同的槽函数,只要该槽函数中不设置同步控制(如互斥对象),函数就不会阻塞的,函数体本身就是一份执行代码而已。特别提醒一下:Singal和Slot在调用中可能被阻塞的,这个要看信号和槽的连接方式。
weixin_38065414 2019-09-19
  • 打赏
  • 举报
回复
信号和槽 在一个线程里 完全不用担心这个问题 重载event()也不会造成困扰在多线程环境下 跨线程链接 注意链接方式
weixin_38066537 2019-09-19
  • 打赏
  • 举报
回复
版主没有看清楚我的回复,我回答的很清楚的了而版主又把物理牵涉进来,我感觉我连累了物理,哈哈其实很简单的,程序的单线程并不是一定就按顺序执行,如定时器、网络访问等呵呵,版主没有明白我的意思
weixin_38067090 2019-09-19
  • 打赏
  • 举报
回复
我表示围观不语,看大牛讨论技术,打的难解难分
weixin_38067167 2019-09-19
  • 打赏
  • 举报
回复
我是个新手,这两天才自学的Qt,想做个东西,就突然想到了这个问题,Qt手册上也没讲,所以就想问问大家,感觉大家都好厉害!
weixin_38078242 2019-09-19
  • 打赏
  • 举报
回复
提提我个人的看法:Qt信号槽在不同的操作系统在执行上是存在不同的结果的,毕竟QT只是C++层面上的包装,也就是说Qt是建立在软件层面上的东西,它没有过多考虑硬中断对其的影响,或者说它把原子操作这类的问题交给操作系统处理。但不同的操作系统对硬中断和软中断处理方法是不一致的。举个例子:QNX类的实时系统与普通的UNIX系统(如AIX、BSD、HP-UX、LINUX等)甚至Win系统是相差很远,这是和CPU设计有莫大关系。所以DeBao兄和cahwxy兄讲法其实都没有问题。真理也往往在讨论中发现,支持大家多讨论但不要涉及个人词语。您们觉得呢?begboy
weixin_38088281 2019-09-19
  • 打赏
  • 举报
回复
main.cpp:return app.exec(); qapplication.cpp:int QApplication::exec(){    return QGuiApplication::exec();} qguiapplication.cpp:int QGuiApplication::exec(){#ifndef QT_NO_ACCESSIBILITY    QAccessible::setRootObject(qApp);#endif    return QCoreApplication::exec();} qcoreapplication.cpp:int QCoreApplication::exec(){    ....    int returnCode = eventLoop.exec();    ....} qeventloop.cpp:int QEventLoop::exec(ProcessEventsFlags flags){    ....     while (!d->exit.loadAcquire())        processEvents(flags | WaitForMoreEvents | EventLoopExec);    ....} 大至如此,我没有仔细的看,但看来和windows类似,现代操作系统基本上都是基于事件/消息模式,QT是事件驱动的,在Windows中是Message,在Qt中是Event,Windows中有消息循环和消息派发, 在Qt中有事件循环和事件派发,so,单线程就是顺序执行,即使有中断事件的产生,也是通过发送消息/事件到队列,取消息/事件,执行消息/事件,循环往复,直至取到退出事件。 再想想,为什么定时器的时间不够准确,你定时1秒,再运行一个超过1秒的函数,定时器事件必定要在函数执行完成后才能响应定时器事件。即便系统有硬中断产生,也是同样处理,系统底层是有中断响应的,但到应用层还是通过消息/事件通知的。比如串口,如果不用多线程方式读取,在你执行一个长任务时,串口过来的数据你是不会马上读到的,如果缓冲区不够,而串口数据又太多的话,就会造成串口数据丢失,目前Qt所带的串口类好像有两种方式,一种轮询,一种是事件。 我只是想表达的是,单线程就是顺序执行,没有例外,关键是要理解这个顺序,GUI程序如同单片机程序一样,总有一个 “循环处理”:main(){    // 前处理    while(主线程.取出事件() != 退出)        处理事件();    // 退出后处理}我喜欢这样说,GUI程序中,顺序是指main()或其它入口函数中的语句执行顺序,具体到某个事件的话,要看事件在事件队列中的顺序,大致如此。 对于楼主的情况,cahwxy说的槽函数的同步控制什么的,我真心没注意去看,暂时也用不到,就偷懒了,但如果只是使用默认的参数来设置信号槽的话,那就一定是阻塞的。 当一个信号被发射时,与其相关联的槽将被立刻执行,就象一个正常的函数调用一样。信号 - 槽机制完全独立于任何 GUI 事件循环。只有当所有的槽返回以后发射函数(emit)才返回。 如果存在多个槽与某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地 执行,但是它们执行的顺序将会是随机的、不确定的,我们不能人为地指定哪个先执行、哪 个后执行。 connect(this, &MainWindow::emit1, this, &MainWindow::onSlot); void MainWindow::on_pushButton_clicked(){    emit this->emit1();} void MainWindow::onSlot(){    j++;    qDebug() << "j" << j;    emit this->emit1();    i++;   qDebug() << i;} j 4262j 4263j 4264j 4265j 4266j 4267j 4268j 4269j 4270j 4271j 4272j 4273j 4274j 4275j 4276j 4277j 4278j 4279j 4280j 4281j 4282j 4283j 4284j 4285j 4286j 4287j 4288j 4289j 4290j 4291j 4292j 4293j 4294j 4295j 4296j 4297j 4298j 4299j 4300j 4301j 4302j 4303j 4304j 4305j 4306j 4307j 4308j 4309j 4310程序异常结束。 嗯,程序永远不会i++,也许例子极端,但就是这样。 这几个字打了一小时,有监控,怕被老板发现
weixin_38089851 2019-09-19
  • 打赏
  • 举报
回复
常规情况下,你可以认为信号槽机制就是一个优化了过的,不会产生 core dumps 的回调函数。如果深点说,Qt的信号槽机制其实就是按照名称查表,类似C++虚函数表机制,Qt是查元数据表。首先生成表,发射信号时:void MainWindow::emit1(){// 首先把参数打包,此处没有    // 然后调用元数据类的激活    QMetaObject::activate(this, &staticMetaObject, 0, _a);}查表,然后调用:qt_metacall(),// 响应信号是在moc里实现的int MainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a){    ....        // 这里调用真正的方法        switch (_id) {         case 0:***        }    ....}要是想深入,就静下心看源码,一、两个小时的事,要不就简单理解就行了。
weixin_38093364 2019-09-19
  • 打赏
  • 举报
回复
当一个信号被发射时,与其相关联的槽将被立刻执行, Qt真的确保这一点吗?我们以分时系统UNIX(LINUX)为例来深入思考一下:为满足多用户多任务的要求,现代的操作系统一般会将用户进程(程序)执行分成多个级别,简化来讲主要分成用户和核心2级。核心一级主要负责对CPU的时间调度、周边硬件设备的管理、中断的处理、进程调度、存储管理等等。当QT在UNIX执行信号槽时,核心如何处理呢?第一种情况:信号槽不涉及硬件资源的处理;第二种情况:信号槽涉及硬件资源的处理;对于第一种情况,系统仅以软件中断级别处理(低优先级)对于第二种情况,系统则进入硬件中断级别处理(高优先级)以经典的UNIX类系统中断级来参考:从高到低:1、    机器错误;2、    时钟;3、    磁盘;4、    网络设备;5、    终端;6、    软件中断;我们大部分程序的运行涉及中断的基本在软件中断这个低优先级层次,是极容易被高优先级中断的,对于被中断的用户进程核心会做一个上下文切换。但核心一定会长期保持这个上下文映象吗?非也。当核心一直有高优先级的中断需要处理,当用户进程的挂起超过操作系统核心设定的冻结时间,用户进程在不同操作系统结果是不同的,甚至进程被取消。举个例子可能会更明了:有个屁民张三感冒了,一开始只是打个喷嚏。他到了省城最大的医院去看病。挂号排队,排第八。等啊等啊,前面七个看完了,终于轮到他,这时张三已经开始流鼻水了。忽然来了一个院长太太,护士长直接带进医生处理了,张三只好继续等;终于院长太太走了,张三刚一站起来,又来了个县长夫人,张三又坐下了。等啊等啊,又来了个市长夫人,张三又坐下了。这时张三已经发抖了。。。等啊等啊,又来了个省长夫人,。。。最终来了个宇宙夫人。。。。张三再也站不起来了。。。。 故事纯属虚构,大家就乐乐吧。begboy
weixin_38098649 2019-09-19
  • 打赏
  • 举报
回复
QTCN就需要这样的讨论! 收益匪浅啊。
weixin_38102396 2019-09-19
  • 打赏
  • 举报
回复
受益匪浅
weixin_38118871 2019-09-19
  • 打赏
  • 举报
回复
又复习了一遍,又更正了一次自己的知识,受教,谢谢!
weixin_38121257 2019-09-19
  • 打赏
  • 举报
回复
真的是获益匪浅 同样的信号槽机制,针对不同的“场景”,不同的系统,会产生不同的效果。
weixin_38049129 2019-09-19
  • 打赏
  • 举报
回复
自己写一个小程序试一下不就可以看到是什么结果啦。这里有个例子可以参考一下http://www.qtcn.org/bbs/read-htm-tid-55192-ds-1-page-2.html#150083
weixin_38053515 2019-09-19
  • 打赏
  • 举报
回复
单线程是不存在这种困扰的,因为是顺序执行,在一个槽没处理完的时候,不会激发另一个槽程序,除非你的CPU在单线程可以使用影分身。多线程也是一样的,使用直连会出你这个问题,使用队列不会的。

476

社区成员

发帖
与我相关
我的任务
社区描述
其他技术讨论专区
其他 技术论坛(原bbs)
社区管理员
  • 其他技术讨论专区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧