Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

qthread

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

like image 843
user63898 Avatar asked Jun 06 '11 12:06

user63898


3 Answers

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();
like image 173
Gunther Piez Avatar answered Oct 13 '22 00:10

Gunther Piez


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.

like image 28
Aki Avatar answered Oct 13 '22 01:10

Aki


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.

like image 22
O.C. Avatar answered Oct 13 '22 02:10

O.C.