QT threads :Getting QObject::startTimer: timers cannot be started from another thread warning

user63898 picture user63898 · Jun 6, 2011 · Viewed 33.3k times · Source

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

Answer

Gunther Piez picture Gunther Piez · Jun 6, 2011

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