zoukankan      html  css  js  c++  java
  • 除了信号触发线程与接收者线程相同的情况能直接调用到slot,其它情况都依赖事件机制(解决上面代码收不到信号的问题其实很简单,在线程的run();函数中添加一个事件循环就可以了,即加入一句exec();),信号槽不就是一个回调函数嘛

    1. MainWindow::MainWindow(QWidget *parent) :
    2.  
      QMainWindow(parent)
    3.  
      {
    4.  
      pThreadCon = new CSerialThread();
    5.  
      pThreadCon->start();
    6.  
       
    7.  
      m_pTimer = new QTimer();
    8.  
      connect(m_pTimer,SIGNAL(timeout()),SLOT(onTimer()));
    9.  
      m_pTimer->start(1000);
    10.  
      }
    11.  
       
    12.  
      void MainWindow::onTimer()
    13.  
      {
    14.  
      m_pTimer->stop();
    15.  
      connect(this,SIGNAL(onSignal()),g_pThread,SLOT(onTimer()),Qt::QueuedConnection);
    16.  
      emit onSignal();
    17.  
      this->disconnect();
    18.  
      }
    19.  
       
    20.  
       
    21.  
      void CSerialThread::run()
    22.  
      {
    23.  
      g_pThread = new CThread();
    24.  
      }
    25.  
       
    26.  
      CThread::CThread(QObject *parent) :
    27.  
      QThread(parent)
    28.  
      {
    29.  
      }
    30.  
       
    31.  
      void CThread::onTimer()
    32.  
      {
    33.  
      sleep(5);
    34.  
      qDebug("------onTimer call");
    35.  
      }

    只添加了部分代码,运行这个程序是看不到打印信息的,说明这个信号没有接收到,如果将connect最后一个参数改成直接连接,会有打印,但是主界面会卡住5秒。一直被这个问题困扰,为什么g_pThread 收不到信号呢,首先应该知道,Qt的信号和槽是基于事件循环的,就像main函数最后都会有一句 return exec();这里就启动了事件循环,除了信号触发线程与接收者线程相同的情况能直接调用到slot,其它情况都依赖事件机制。QThread::run()实际上是简单调用了QThread::exec(),而它启动了线程的事件循环,但是run()函数结束后,事件循环结束了,这个时候我们再发送信号,没有事件循环的支持,g_pThread就收不到信号了。

    QThread的内部结构非常有趣:

    • QThread并不生存于执行run()的新线程内。它生存于旧线程中。
    • QThread的大多数成员方法是线程的控制接口,并设计成从旧线程中被调用。不要使用moveToThread()将该接口移动到新创建的线程中;调用moveToThread(this)被视为不好的实践。
    • exec()和静态方法usleep()、msleep()、sleep()要在新创建的线程中调用。
    • QThread子类中定义的其他成员可在两个线程中访问。开发人员负责访问的控制。一个典型的策略是在start()被调用前设置成员变量。一旦工作线程开始运行,主线程不应该操作其他成员。当工作线程终止后,主线程可以再次访问其他成员。这是一个在线程开始前传递参数并在结束后收集结果的便捷的策略。

    QObject必须始终和parent在同一个线程。

    所以解决上面代码收不到信号的问题其实很简单,在线程的run();函数中添加一个事件循环就可以了,即加入一句exec();

    有不对的地方希望大家指正,相互学习。

    https://blog.csdn.net/sddsighhz/article/details/36894247

    成都-陈剑客
    信号槽不就是一个回调函数嘛
    他啥也不依赖
    你可以这么干
    取得函数地址
    然后把这个地址设置到emit的地方
    效果和信号槽一模一样

  • 相关阅读:
    Dapper数据库字段和model属性映射
    SQLServer性能调优之缓存
    python&django 实现页面中关联查询小功能(基础篇)
    pythonのdjango select_related 和 prefetch_related()
    pythonのdjango 在控制台用log打印操作日志
    pythonのdjango Form简单应用。
    pythonのdjango 信号
    pythonのdjango 缓存
    pythonのdjango CSRF简单使用
    pythonのdjango Session体验
  • 原文地址:https://www.cnblogs.com/findumars/p/9550910.html
Copyright © 2011-2022 走看看