Qt 子线程 所有权

// worker类,继承,OBject,头文件
class worker : public QObject
{
    Q_OBJECT
public:
    explicit worker(QObject *parent = nullptr);
    void test();

public slots:
    void dowork1();
    void dowork2();
    void dowork3();

signals:
    void singalwork();
};

//worker实现
worker::worker(QObject *parent) : QObject(parent)
{
    qDebug() << " Workd Create , 当前ThreadID:"<<QThread::currentThreadId();
}

void worker::test()
{
    qDebug() << " Workd Test FUNC 成员函数ThreadID:"<<QThread::currentThreadId();
}

void worker::dowork1()
{
    qDebug() << "doWork1 ThreadID:"<<QThread::currentThreadId();
}

void worker::dowork2()
{
    qDebug() << "doWork2 ThreadID:"<<QThread::currentThreadId();
}

void worker::dowork3()
{
    qDebug() << "doWork3 ThreadID:"<<QThread::currentThreadId();
}

int main()
{
    // OBJECT 线程
    mywork = new worker();
    thr1 = new QThread();

    mywork->moveToThread(thr1);

    QObject::connect(thr1, &QThread::started,mywork,[=](){ mywork->dowork2(); });        //dowork2在子线程执行

    /*

    解释:
    connect(sender, signal, lambda);
    等于
    connect(sender, signal, sender, lambda);

    // 这样才会跑在主线程!
    connect(thr1, &QThread::started, this, [=](){
        mywork->dowork2();  // 这里会在主线程执行!!!
    });

    // 假设 started 信号带参数:started(int value) 线程传参
    QObject::connect(thr1, &QThread::started, mywork, [=](int value){
        // 这里可以直接用 value!
        qDebug() << "收到参数:" << value;

        // 原来的逻辑不变
        mywork->dowork2();
    });


    //变量捕获,[=]  [&] 用法:

    1、只读、简单变量 → 用 [=](值捕获)
    安全,无野指针 / 悬空引用风险,
    int a = 99;
    QString test = "this is a test string!";

    // [=] 是值捕获:把 a 和 test 复制一份存到 Lambda 里
    connect(thr1, &QThread::started, this, [=](){
        qDebug() << "a:" << a << "test:" << test; 
        mywork->dowork2(); 

        // 这里编译器自动生成了一个 【副本 int a = 99;】
        fun(&a); //这里的副本a的生命周期,和Lambda同生共死。
    });

    // 这种也是拷贝
    connect(thr1, &QThread::started, thr1, [a, test, mywork](){
      qDebug() << a << test;
      mywork->dowork2();
    });

    2. 需要修改原变量 → 用 [&](引用捕获)
    必须保证:变量生命周期 > Lambda 执行时间,否则会崩溃
    connect(thr1, &QThread::started, thr1, [&](){
        a = 100; // 修改原变量
        test = "ok"; 
    });
        
    // 还有一种,invoke触发  和  //mywork->dowork2();//主线程执行 
    // 想实现的类似, invoke触发的//是子线程执行
    QMetaObject::invokeMethod(
        myUart,          // 1. 目标:子线程里的 uartWork
        "sendData",        // 2. 要调用的槽函数名字(必须加引号)
        Qt::QueuedConnection, // 3. 固定:跨线程队列调用
        Q_ARG(QByteArray,sendData) // 4. 参数1:类型+值
    );

    */

    QObject::connect(thr1, &QThread::started, mywork, &worker::dowork1);         //第一槽函数
    QObject::connect(mywork, &worker::singalwork, mywork, &worker::dowork3);     //第三槽函数

    //mywork->dowork2();//主线程执行
    //QObject::connect(thr1, &QThread::started, mywork, &worker::dowork2);        //子线程执行

    // 线程的moveToThread,把mywork的所有槽函数都转入线程,所以,信号singalwork触发也是,dowork3,也是线程执行
    thr1->start();

    // 相当于 在这里答应ThreadID
    mywork->test();
    qDebug() << "MainWindow 成员函数ThreadID:"<<QThread::currentThreadId();

    //发送自定义信号
    emit mywork->singalwork();
}



posted @ 2026-03-30 12:29  一见无始道成空  阅读(3)  评论(0)    收藏  举报