简体   繁体   English

QTimer未在线程中触发

[英]QTimer not firing in a thread

I have an Qt5 c++ app with 2 threads, thread A is started when the main program starts up. 我有一个带有2个线程的Qt5 c ++应用程序,主程序启动时启动了线程A。 The start method of thread A runs successfully. 线程A的启动方法成功运行。

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! 接下来,在主程序中,我向线程A发送一个信号以启动QTimer,它确实可以-但是该计时器永不过期!

Thread B handles tcp connections. 线程B处理tcp连接。 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. 当我启动与应用程序的telnet连接时,线程B启动,突然我看到线程A的Qtimer以正常间隔过期。

Why is the QTimer from thread A not expiring until thread B starts? 为什么直到线程B启动,线程A的QTimer才到期?

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)与计时器对象处于不同的线程中。 This timer thread address is actually the MAIN thread. 此计时器线程地址实际上是MAIN线程。 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): 它在我的线程(TheController对象)中运行一个插槽:

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();

Well, it's not a Qt5 bug, it's more an inaccurate understanding of Qt's thread spirit. 好吧,这不是Qt5的错误,而是对Qt的线程精神的不准确的了解。

In Qt, you have two ways to implement a thread which are using or not an even loop. 在Qt中,有两种实现线程的方法,它们使用的是偶数循环,也可以不使用偶数循环。 Here is just a small visual example. 这只是一个小的视觉示例。

No event loop 没有事件循环

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

With an event loop 具有事件循环

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

(Of course you can mix a do/while with an even loop but stay simple). (当然,您可以将一个do / while与一个偶数循环混合在一起,但保持简单)。

In QTimer's doc, you can read: 在QTimer的文档中,您可以阅读:

In multithreaded applications, you can use QTimer in any thread that has an event loop. 在多线程应用程序中,可以在具有事件循环的任何线程中使用QTimer。 [...] Qt uses the timer's thread affinity to determine which thread will emit the timeout() signal. [...] Qt使用计时器的线程关联性来确定哪个线程将发出timeout()信号。 Because of this, you must start and stop the timer in its thread; 因此,您必须在其线程中启动和停止计时器。 it is not possible to start a timer from another thread. 无法从另一个线程启动计时器。

So i'm pretty sure you don't have a second event loop in your second thread and that's why you have the behaviour you described. 因此,我非常确定您在第二个线程中没有第二个事件循环,这就是您具有所描述的行为的原因。

To give you some tips to be totally clear with thread using Qt, I suggest you to read: 为了给您一些使用Qt完全清楚了解线程的提示,建议您阅读以下内容:

and a very good article about how QThread implementation is misunderstandood by a lot of user. 一篇非常好的文章,介绍了许多用户如何误解QThread实现。 - You're doing it wrong: http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/ -您做错了: http : //blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/

I hope it will help ;) 我希望它会有所帮助;)

The best answer seems to be a combination of RobbieE and Kuba: 最好的答案似乎是RobbieE和Kuba的结合:

You have to explicitly set the parent of the member variable in constructor. 您必须在构造函数中显式设置成员变量的父级。 The parent-child feature is a Qt thing that exists among classes derived from QObject, it is not a feature of C++. 父子功能是Qt事物,它存在于从QObject派生的类中,而不是C ++的功能。

I never knew this - I assumed that when an object was created, its members variables automatically had their parent set to the object. 我从来不知道这一点-我假设创建对象时,其成员变量会自动将其父对象设置为该对象。 Good to know!! 很高兴知道!!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM