0

I have an Qt5 c++ app with 2 threads, thread A is started when the main program starts up. The start method of thread A runs successfully.

So far so good. Next, in the main program I send a signal to Thread A to start a QTimer, which it does - but that timer never expires!

Thread B handles tcp connections. When I initiate a telnet connection to my app, thread B fires up and suddenly I see my Qtimer from thread A expiring at normal intervals.

Why is the QTimer from thread A not expiring until thread B starts?

I suspect my threads are getting messed up. note the last section of code below products this:

thread of this:  QThread(0x200fe00)  
thread of timer:  QThread(0x1fff470)

Which suggest my worker object (this), is in a different thread from my timer object. This timer thread address is actually the MAIN thread. Why? I'm confused.

Suggestions?


In my main app I create and start my thread like this:

QThread * MyControllerThread = new QThread(this);

if (MyControllerThread) {

    TheController *worker = new TheController(MyControllerThread);

    if (worker) {
        connect(MyControllerThread, SIGNAL(started()), worker, SLOT(start()));
        connect(MyControllerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
        connect(MyControllerThread, SIGNAL(finished()), MyControllerThread, SLOT(deleteLater()));
        worker->moveToThread(MyControllerThread);  
        MyControllerThread->start();  
    } 

and in my main app I emit a signal to the new thread:

    emit sig_startlocalpeer(Types::EActionLocalServiceStart);  // Move the local peer to standby mode to start remote tests

which runs a slot in my thread (TheController object):

connect(&m_remotetestintervaltimer,SIGNAL(timeout()),this,SLOT(expiredRemoteTestIntervalTimer()));
m_remotetestintervaltimer.setTimerType(Qt::VeryCoarseTimer);
m_remotetestintervaltimer.start(REMOTETEST_TIMER_INTERVAL);  // Wait between ticks
qDebug() << "thread of this: " << this->thread();
qDebug() << "thread of timer: " << m_remotetestintervaltimer.thread();
4

2 回答 2

1

嗯,这不是Qt5的bug,更多的是对Qt的线程精神理解不准确。

在 Qt 中,您有两种方法来实现使用或不使用偶数循环的线程。这只是一个小的视觉示例。

没有事件循环

myMethodCalledInANewThread
{
    do{ ... }while(...);
}

使用事件循环

myMethodCalledInANewThread
{
    [...]
    exec();
}

(当然,您可以将 do/while 与偶数循环混合,但要保持简单)。

在 QTimer 的文档中,您可以阅读:

在多线程应用程序中,您可以在任何具有事件循环的线程中使用 QTimer。[...] Qt 使用计时器的线程亲和性来确定哪个线程将发出 timeout() 信号。因此,您必须在其线程中启动和停止计时器;无法从另一个线程启动计时器。

所以我很确定你的第二个线程中没有第二个事件循环,这就是为什么你有你描述的行为。

为了给您一些提示以完全清楚使用 Qt 的线程,我建议您阅读:

还有一篇关于 QThread 实现如何被很多用户误解的非常好的文章:

我希望它会有所帮助;)

于 2014-08-10T09:53:48.860 回答
-1

最好的答案似乎是 RobbieE 和 Kuba 的组合:

您必须在构造函数中显式设置成员变量的父级。父子特性是存在于从 QObject 派生的类中的 Qt 事物,它不是 C++ 的特性。

我从来不知道这一点——我假设当一个对象被创建时,它的成员变量会自动将它们的父级设置为该对象。很高兴知道!!

于 2014-08-10T03:10:54.683 回答