调用QObject的函数移动到Qt中的不同线程?

时间:2013-12-25 15:29:20

标签: c++ multithreading qt

虽然我对QObjectQThread以及如何在Qt中使用多线程有相当多的了解,但我无法理解某些场景。 考虑将class Myclass : QObject移至另一个QThread

class MyClass : QObject
{
public slots:
    void slot1();
    bool slot2();
    void slot3(); 
}

我有一个班级

class Window
{
signals:
    void sig1();
    bool sig2();

private:
    MyClass *myObj;

public:
void func()
{
    connect(this, SIGNAL(sig1()), myObj, SLOT(slot1()), Qt::DirectConnection);
    emit sig1();
    qDebug("SIGNAL1 emitted!");

    connect(this, SIGNAL(sig2(bool)), myObj, SLOT(slot2(bool)));
    bool result = emit sig2();

    myObj->slot3();
}

}
  1. 发出sig1后,我了解只有在qDebug()执行后才会执行slot1()。但是slot1Window thread

  2. 执行了MyClass thread
  3. 如果sig2保证result将存储slot2返回的值,或者此连接是否必须是直接的?

  4. 如图所示运行slot3是否正确? slot3修改myObj的类变量,并发出SIGNAL,该SLOT与调用Window object的{​​{1}}相关联。如果它是正确的,那么Window的插槽何时执行以及在哪个线程中?

2 个答案:

答案 0 :(得分:2)

  

当发出sig1时,我知道只有在执行slot1()之后才会执行qDebug()。

默认情况下不保证。只要Qt事件循环将其调回,就可以在函数或方法之前或之后在connect语句之后调用该槽。如果为最后一个参数Qt :: ConnectionType`指定直接连接,则将保证立即调用。有关详细信息,请参阅文档:

  

Qt :: DirectConnection 1当发出信号时,立即调用插槽。

但是,如果您没有明确指定,Qt::AutoConnection是默认值。

  

但是在Window线程或MyClass线程中执行了slot1吗?

它再次取决于连接类型参数。有关详细信息,请参阅documentation

简而言之,如果它排队,则在接收者的线程中执行,否则从与接收者不同的线程执行。

  

如果sig2保证结果将存储slot2返回的值,或者此连接是否必须是直接的?

这看起来不对。信号意味着要避免,并且您不能将它们的返回值存储为函数或方法返回值,期望它是连接槽的结果。

即使你可以,也会让人感到困惑,因为同一个信号可以连接多个插槽。更重要的是,信号可以连接到信号。

  

如图所示运行slot3是否正确? slot3修改myObj的类变量,并发出一个连接到调用Window对象的SLOT的SIGNAL。如果它是正确的,那么什么时候执行Window的插槽和哪个线程?

是的,您可以这样调用它,因为插槽只是常规函数,通常具有void返回值类型。

答案 1 :(得分:1)

问题#1。如果您没有在默认情况下强制DirectConnection,则在不久的将来某个时间将在包含MyClass的线程中执行插槽1。这种方式的工作方式是默认情况下信号/插槽将使用QueuedConnection作为交叉线程信号和插槽。

也是你的

qDebug("SIGNAL1 emitted!");
默认情况下执行slot1()后,不保证执行

。如果包含MyClass对象的线程忙,则slot1()的执行将被延迟()。

但是,由于您强制DirectConnection slot1()将在发出信号的线程中执行,并且在qDebug返回之前也将保证执行。

问题#2。我认为连接需要是直接的,才能正确返回结果的值。我相信你必须强制直接连接才能发挥作用。并且还要记住,强制DirectConnection意味着插槽的执行将发生在发出信号的线程中,而不是发生拥有MyClass的线程。我相信文档不鼓励使用插槽中的返回值,所以我从未在生产代码中这样做过。不使用返回值的一个原因是,如果将多个插槽连接到同一信号,则会出现令人困惑的行为。

问题#3。你可以这样做但请记住,代码将在当前线程中执行,而不是拥有MyClass的线程。