14

I follow the examples from the Qt SDK, starting timer in the QThread Subclass but I keep getting the warning and the thread never starts the timer. Here is the code:

NotificationThread::NotificationThread(QObject *parent)
           :QThread(parent),
           m_timerInterval(0)
{
 moveToThread(this);
}


NotificationThread::~NotificationThread()
{
 ;
}

void NotificationThread::fire()
{
  WRITELOG("A::fire called -- currentThread:" + QString::number((int)currentThread()->currentThreadId()));
  QVector<StringPer>* batchVectorResult = new QVector<StringPer>();   
  emit UpdateGroupNotifications(batchVectorResult);

}

void NotificationThread::run()
{

      connect(&m_NotificationTimer, SIGNAL(timeout()),
              this,SLOT(fire(),Qt::DirectConnection));

      WRITELOG("A::run() worker thread -- currentThread:" + QString::number((int)currentThread()->currentThreadId()));
   //SetNotificationTimerFromConf();
   QVariant val(ConfigSettings::getInstance()->ReadFromSettingsReturnVariant(SETTINGS_KEY_NOTIFICATIONTHREAD));
   int interval = val.toInt();
   m_NotificationTimer.setInterval(interval);
      m_NotificationTimer.start();

      QThread::exec();
}


void NotificationThread::SetNotificationTimerFromConf()
{
 QVariant val(ConfigSettings::getInstance()->ReadFromSettingsReturnVariant(SETTINGS_KEY_NOTIFICATIONTHREAD));
 int interval = val.toInt();
 m_NotificationTimer.setInterval(interval);
}


void NotificationThread::UpdateNotificationTimerRT(int timerInterval)
{
 m_NotificationTimer.setInterval(m_timerInterval);
}


void NotificationThread::Execute(const QStringList batchReqList)
{
 QVector<QString>* batchVectorResult = new QVector<QString>();   
 start();
}

I start the Thread from the main GUI with Execute( ).

eddie
  • 1,252
  • 3
  • 15
  • 20
user63898
  • 29,839
  • 85
  • 272
  • 514

3 Answers3

17

The problem is that you create the timer implicitly by the main thread when you create your thread object. This is because your timer is a member of your thread class.

When you try to start the timer, you do in a different thread (in run()), not in the thread where the timer was created, which gives you the warning.

You need to create the timer in the thread where you want to run it:. Change the declaration of m_notificationTimer in your NotificcationThread class from

QTimer m_NotificationTimer;

to

QTimer* m_NotificationTimer;

and create the timer in run() with

m_NotificationTimer = new QTimer(this);
m_NotificationTimer->setInterval(interval);
m_NotificationTimer->start();
Gunther Piez
  • 29,760
  • 6
  • 71
  • 103
  • 1
    Or just use an initializer list: class MyClass: public QObject { Q_OBJECT public: MyClass() : m_thread(this) {} QTimer m_timer; } – nocnokneo Oct 10 '16 at 15:54
9

If you add the line

m_NotificationTimer.moveToThread(this);

to beginning of run() method of your thread from that point on your timer object will invoke the connected slot within the your thread.

When you first create the timer it will run within your main thread. By moving it to your own thread as above the moveToThread method will change the thread affinity of the timer object.

O.C.
  • 6,711
  • 1
  • 25
  • 26
4

It is also worth mentioning this article

The biggest adjustment for me was to understand that threads in qt are used as an interface, and are not really intended for subclassing. With that being said, I would keep your class and and actual QThread separate. And then just use YourClass.moveToThread( &YourQtThread) to ensure your signals and slots are process on that thread.

Aki
  • 3,709
  • 2
  • 29
  • 37
  • The linked to article moved to http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/ – hcc23 Feb 28 '13 at 15:49