qt 链接线程启动后的槽函数

在 Qt 中,将信号与槽函数连接并在新线程中启动槽函数是一种常见的操作。这通常涉及到 QThread 类以及信号和槽的机制。下面是一个简单的示例,演示了如何在一个新线程中启动一个任务,并在任务完成时通过信号和槽机制通知主线程。

示例代码

  1. 定义一个工作类:这个类将在新线程中执行某些任务。

#include <QObject>  
#include <QThread>  
#include <QDebug>  
  
class Worker : public QObject {  
    Q_OBJECT  
  
public slots:  
    void doWork() {  
        // 模拟一些工作  
        qDebug() << "Worker: Doing work in thread" << QThread::currentThread();  
          
        // 假设工作花费了一些时间  
        QThread::sleep(2);  
  
        // 完成后发出信号  
        emit workFinished();  
    }  
  
signals:  
    void workFinished();  
};
  1. 定义主窗口或主类:在这个类中,我们将创建并启动新线程,并将工作对象移动到该线程中。

#include <QCoreApplication>  
#include <QThread>  
#include <QDebug>  
#include "worker.h"  
  
class MainClass : public QObject {  
    Q_OBJECT  
  
public:  
    MainClass() {  
        Worker* worker = new Worker;  
        QThread* thread = new QThread;  
  
        worker->moveToThread(thread);  
  
        connect(thread, &QThread::started, worker, &Worker::doWork);  
        connect(worker, &Worker::workFinished, this, &MainClass::onWorkFinished);  
        connect(worker, &Worker::workFinished, thread, &QThread::quit);  
        connect(thread, &QThread::finished, worker, &QObject::deleteLater);  
        connect(thread, &QThread::finished, thread, &QObject::deleteLater);  
  
        thread->start();  
    }  
  
public slots:  
    void onWorkFinished() {  
        qDebug() << "MainClass: Work finished in thread" << QThread::currentThread();  
    }  
};  
  
int main(int argc, char *argv[]) {  
    QCoreApplication a(argc, argv);  
  
    MainClass mainClass;  
  
    return a.exec();  
}  
  
#include "main.moc"

解释

  1. Worker 类
    • 继承自 QObject 并声明为 Q_OBJECT 以使用信号和槽。
    • 定义一个槽函数 doWork,在这个函数中执行需要在新线程中运行的任务。
    • 定义一个信号 workFinished,当任务完成时发出这个信号。
  2. MainClass 类
    • 在构造函数中,创建 Worker 对象和 QThread 对象。
    • 使用 moveToThread 将 Worker 对象移动到新线程中。
    • 连接信号和槽:
      • 当线程启动时 (QThread::started),调用 Worker 的 doWork 槽函数。
      • 当 Worker 完成工作时 (Worker::workFinished),调用 MainClass 的 onWorkFinished 槽函数,并停止线程 (QThread::quit)。
      • 当线程停止时 (QThread::finished),删除 Worker 和 QThread 对象以释放资源。
    • 启动线程。
  3. main 函数
    • 创建 QCoreApplication 对象。
    • 创建 MainClass 对象,在其中进行所有的设置和线程操作。
    • 进入事件循环。

通过这种方式,你可以将耗时的任务放在新线程中执行,并在任务完成时通过信号和槽机制通知主线程。

### Qt 中跨线程 Signal 不调用 Slot 函数的原因及解决方案 当遇到Qt中跨线程传递信号但不触发槽函数的问题时,通常是因为接收者所在的线程没有正常运行的消息循环。消息循环对于处理事件和调度任务至关重要,在Qt框架下尤其如此。 如果子线程中的`CSignalSlot`对象所属线程的消息循环未启动或已经退出,则即使成功建立了信号与槽之间的连接,也不会有任何反应发生[^3]。这意味着尽管发送方能够发出信号,但由于目标线程缺乏活跃的消息循环来处理这些信号,所以对应的槽函数无法被执行。 #### 启动并保持线程内的事件循环 确保每一个需要响应来自其他线程信号的对象都位于拥有活动事件循环的线程之中非常重要。可以通过调用`QThread::exec()`方法开启一个新的事件循环;而通过继承自`QThread`类重写其虚函数`run()`, 并在其内部调用`exec()`可以实现这一点。另外需要注意的是,只有在线程真正开始之后才会进入这个无限等待的状态——这通常是通过调用`start()`完成的,它不仅会启动线程还会自动调用`exec()`从而激活该线程上的事件循环。 ```cpp void MyThreadClass::run() { exec(); } ``` #### 正确设置连接类型 另一个潜在问题是,默认情况下使用的连接类型可能是`Qt::DirectConnection`而不是更合适的`Qt::QueuedConnection`。前者意味着槽将在发射者的上下文中立即被调用,这对于不同线程间通信来说显然是不可取的行为模式,因为这样可能会破坏线程安全性假设。相反地,后者则允许系统安排一次异步回调给定的目标对象所处的那个特定队列里去执行相应的操作[^1]。 要显式指定这种类型的链接可以在建立联系的时候这样做: ```cpp connect(sender, SIGNAL(signal()), receiver, SLOT(slot()), Qt::QueuedConnection); ``` 或者在现代C++风格下的语法如下所示: ```cpp connect(sender, &Sender::signalName, receiver, &Receiver::slotName, Qt::QueuedConnection); ``` 以上措施应该能有效解决大多数关于Qt线程环境下信号槽机制失效的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值