Потоки QT: Получение QObject :: startTimer: таймеры не могут быть запущены из другого потока предупреждений - PullRequest
6 голосов
/ 06 июня 2011

Я следую примеру из Qt SDK, запуская таймер в подклассе QThread но я продолжаю получать предупреждение, и поток никогда не запускает таймер. Вот код:

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

Я запускаю тему из основного графического интерфейса с Execute( ).

Ответы [ 3 ]

13 голосов
/ 06 июня 2011

Проблема в том, что вы создаете таймер неявно основным потоком при создании объекта потока.Это потому, что ваш таймер является членом вашего класса потока.

Когда вы пытаетесь запустить таймер, вы работаете в другом потоке (в run()), а не в потоке, где был создан таймер,который выдает предупреждение.

Вам необходимо создать таймер в потоке, в котором вы хотите его запустить :.Измените объявление m_notificationTimer в вашем NotificcationThread классе с

QTimer m_NotificationTimer;

на

QTimer* m_NotificationTimer;

и создайте таймер в run() с помощью

m_NotificationTimer = new QTimer(this);
m_NotificationTimer->setInterval(interval);
m_NotificationTimer->start();
8 голосов
/ 06 июня 2011

Если вы добавите строку

m_NotificationTimer.moveToThread(this);

в начало run () , метод вашего потока с этой точки вашего объекта таймера вызовет подключенный слот в вашем потоке.

Когда вы впервые создаете таймер, он будет работать в вашем основном потоке.Перемещая его в свой собственный поток, как описано выше, метод moveToThread изменит сродство потока объекта таймера.

3 голосов
/ 09 декабря 2011

Стоит также упомянуть эту статью

Самым большим изменением для меня было понимание того, что потоки в qt используются как интерфейс и не предназначены для создания подклассов. С учетом вышесказанного, я бы оставил ваш класс и фактический QThread отдельно. А затем просто используйте YourClass.moveToThread (& YourQtThread), чтобы убедиться, что ваши сигналы и слоты обрабатываются в этом потоке.

...