C++ QT 线程:获取 QObject::startTimer:计时器无法从另一个线程启动警告

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6252146/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 19:46:37  来源:igfitidea点击:

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

c++qthread

提问by user63898

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

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

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

我从主 GUI 启动线程Execute( )

采纳答案by O.C.

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.

从计时器对象上的那个点到线程的run()方法的开始将调用线程中的连接槽。

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

当您第一次创建计时器时,它将在您的主线程中运行。通过将其移动到您自己的线程,如上,moveToThread方法将更改计时器对象的线程关联。

回答by Gunther Piez

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.

当您尝试启动计时器时,您会在不同的线程 (in run()) 中执行操作,而不是在创建计时器的线程中执行,这会向您发出警告。

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

您需要在要运行它的线程中创建计时器:。m_notificationTimerNotificcationThread类中的声明从

QTimer m_NotificationTimer;

to

QTimer* m_NotificationTimer;

and create the timer in run()with

并在run()其中创建计时器

m_NotificationTimer = new QTimer(this);
m_NotificationTimer->setInterval(interval);
m_NotificationTimer->start();

回答by Aki

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.

对我来说最大的调整是理解 qt 中的线程用作接口,而不是真正用于子类化。话虽如此,我会将您的课程和实际 QThread 分开。然后只需使用 YourClass.moveToThread( &YourQtThread) 来确保您的信号和插槽在该线程上处理。