首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在Qt中发出跨线程信号?

如何在Qt中发出跨线程信号?
EN

Stack Overflow用户
提问于 2009-03-12 11:38:16
回答 3查看 88.4K关注 0票数 60

Qt文档说明信号和插槽可以是directqueuedauto

它还指出,如果拥有slot的对象‘生活’在与拥有信号的对象不同的线程中,发出这样的信号将类似于发布消息- signal emit将立即返回,slot方法将在目标线程的事件循环中被调用。

不幸的是,文档并没有指定'lives‘代表什么,也没有可用的例子。我已经尝试了以下代码:

main.h:

代码语言:javascript
复制
class CThread1 : public QThread
{
Q_OBJECT
public:
    void run( void )
    {
        msleep( 200 );
        std::cout << "thread 1 started" << std::endl;
        MySignal();
        exec();
    }
signals:
    void MySignal( void );
};

class CThread2 : public QThread
{
Q_OBJECT
public:
    void run( void )
    {
        std::cout << "thread 2 started" << std::endl;
        exec();
    }
public slots:
    void MySlot( void )
    {
        std::cout << "slot called" << std::endl;
    }
};

main.cpp:

代码语言:javascript
复制
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    CThread1 oThread1;
    CThread2 oThread2;
    QObject::connect( & oThread1, SIGNAL( MySignal() ),
        & oThread2, SLOT( MySlot() ) );
    oThread1.start();
    oThread2.start();
    oThread1.wait();
    oThread2.wait();
    return a.exec();
}

输出为:

代码语言:javascript
复制
thread 2 started
thread 1 started

永远不会调用MySlot() :(.我哪里做错了?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-03-12 13:49:40

你的代码有很多问题:

正如Evan所说,emit关键字缺少

  • 你所有的对象都在主线程中,只有运行方法中的代码在其他线程中,这意味着MySlot插槽将在主线程中被调用,我不确定这是你想要的,因为主事件循环永远不会被启动:你对

()的两次调用

  • ()只会在很长一段时间后超时(在此之前你可能会杀死你的应用程序),我也不认为这是你想要的。无论如何,它们在您的代码中真的没有任何用处。

这段代码很可能会工作(尽管我还没有测试过它),而且我认为它能做你想让它做的事情:

代码语言:javascript
复制
class MyObject : public QObject
{
    Q_OBJECT
public slots:
    void MySlot( void )
    {
        std::cout << "slot called" << std::endl;
    }
};

class CThread1 : public QThread
{
    Q_OBJECT
public:
    void run( void )
    {
        std::cout << "thread 1 started" << std::endl;
        int i = 0;
        while(1)
        {
           msleep( 200 );
           i++;
           if(i==1000)
              emit MySignal();
        }
    }
signals:
    void MySignal( void );
};

class CThread2 : public QThread
{
    Q_OBJECT
public:
    void run( void )
    {
        std::cout << "thread 2 started" << std::endl;
        exec();
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    CThread1 oThread1;
    CThread2 oThread2;
    MyObject myObject;
    QObject::connect( & oThread1, SIGNAL( MySignal() ),
        & myObject, SLOT( MySlot() ) );
    oThread2.start();
    myObject.moveToThread(&oThread2)
    oThread1.start();
    return a.exec();
}

现在MyObject将住在thread2 (多亏了moveToThread)。

MySignal应该是从thread1发送的(虽然我不确定这一点,但它可能是从主线程发送的,这并不重要)。

在thread1中不需要事件循环,因为发出信号不需要事件循环。在thread2 (由exec()调用)中需要一个事件循环来接收信号。

将在thread2中调用MySlot。

票数 48
EN

Stack Overflow用户

发布于 2011-12-03 01:24:34

不要为Qt 4.4+创建QThread子类

虽然Aiua的答案是好的,但我想指出QThread和Qt4.6或4.7的一些问题。

本文对此进行了总结:http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

缺乏关于Qt部分的文档

不幸的是,这个问题源于缺少对文档的更新。在Qt4.4之前,QThread没有默认的run()实现,这意味着您必须继承QThread才能使用它。

如果你使用的是Qt4.6或4.7,那么你几乎肯定不应该继承QThread的子类。

使用moveToThread

正如Aiua指出的那样,让插槽在工作线程中执行的关键是使用moveToThread方法。

票数 39
EN

Stack Overflow用户

发布于 2018-12-22 11:27:50

您应该发出信号来启动线程函数,如下所示

代码语言:javascript
复制
emit operateCut(examId,examName_examTemplate[examName].studentIdRec,examName_examTemplate[examName].choiceRecA,examName_examTemplate[examName].choiceRecB,examName_examTemplate[examName].objectRecA,examName_examTemplate[examName].objectRecB);

您可以在此信号中添加多个参数

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/638251

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档