简体   繁体   English

QTimer :: timeout不触发

[英]QTimer::timeout isn't firing

I am trying to create an event that gets fired off every n seconds in my Singleton worker. 我正在尝试创建一个事件,该事件在我的Singleton工作者中每n秒触发一次。 A signal/slot connection (with the signal being the QTimer timing out and the slot being a lambda function which makes a call to another Singleton class) is not working. 信号/插槽连接(信号为QTimer超时,插槽为lambda函数,该函数调用另一个Singleton类)不起作用。 The connect call is succeeding, the timer is active, and I get no QTimer complaints on the console. 连接调用成功,计时器处于活动状态,并且控制台上没有QTimer投诉。 If I try to print QTimer's remaining time it reads -1. 如果我尝试打印QTimer的剩余时间,它将显示为-1。 For the life of me, I cannot figure out why "timeout" is never being printed (indicating that the event is being triggered). 对于我的一生,我无法弄清楚为什么从未打印“超时”(表明事件已被触发)。 Any help would be greatly appreciated. 任何帮助将不胜感激。 For simplicity's sake we can assume that OtherSingleton has the same structure. 为了简单起见,我们可以假设OtherSingleton具有相同的结构。 I should also note that this Singleton class object is running inside of a QThread. 我还应该注意,此Singleton类对象在QThread内部运行。

Singleton.h: Singleton.h:

#include <QObject>
#include <string>
#include <QTimer>
#include <QThread>

class Singleton : public QObject
{
   Q_OBJECT

public:
    static Singleton& get_instance();

    Singleton(Singleton const&) = delete;
    void operator=(Singleton const&) = delete;

    static void stop_client();

    static void start_client();

private:
    Singleton();

    static QTimer bytes_timer_;

};

Singleton.cpp: Singleton.cpp:

#include "Singleton.h"
#include <QDebug>
#include <QTime>
#include <QFile>

Singleton::Singleton()
{
    bytes_timer_.setParent(this);
    bytes_timer_.moveToThread(QThread::currentThread());
    bytes_timer_.setInterval(1000);
    qDebug() << "Timeout success:" << connect(&bytes_timer_, &QTimer::timeout, this, [&]() {
        qDebug() << "timeout";
        // . . .
    }, Qt::DirectConnection);
}

Singleton& Singleton::get_instance() {
    static Singleton instance; 

    return instance;
}

void Singleton::start_client() {
    bytes_timer_.start();
}

void Singleton::stop_client() {
     bytes_timer_.stop();
}

QTimer Singleton::bytes_timer_;

MainWindow.h: MainWindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QThread>
#include "singleton.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

private:
    QThread thread;
    Singleton *s;
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

MainWindow.cpp: MainWindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    s = &Singleton::get_instance();
    s->moveToThread(&thread);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    thread.start();
    s->start_client();
}

main.cpp: main.cpp中:

#include "mainwindow.h"
#include <QApplication>
#include <QThread>
#include "singleton.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

as documented in the official site, you need to start the timer 如官方网站中所述,您需要启动计时器

bytes_timer_.start();

https://doc.qt.io/qt-5/qtimer.html#start-1 https://doc.qt.io/qt-5/qtimer.html#start-1

I somehow have the feeling that OP is about to “over-engineer” what could be actually quite simple. 我以某种方式感到OP将会“过度设计”实际上可能非常简单的东西。

I made an MCVE to demonstrate this. 我做了一个MCVE来证明这一点。

testQTimerStartStop.cc : testQTimerStartStop.cc

#include <QtWidgets>

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  // prepare application
  QApplication app(argc, argv);
  QTimer qTimer;
  qTimer.setInterval(1000);
  // setup GUI
  QWidget qWinMain;
  qWinMain.setWindowTitle(QString::fromUtf8("QTimer Test"));
  QFormLayout qForm;
  QSpinBox qEditTimer;
  qEditTimer.setRange(0, 30);
  qForm.addRow(
    QString::fromUtf8("Count down:"),
    &qEditTimer);
  QPushButton qBtnStart(QString::fromUtf8("Start"));
  qForm.addRow(&qBtnStart);
  QPushButton qBtnStop(QString::fromUtf8("Stop"));
  qForm.addRow(&qBtnStop);
  qWinMain.setLayout(&qForm);
  qWinMain.show();
  // set initial states
  qEditTimer.setValue(10);
  auto updateBtns = [&]() {
    const int count = qEditTimer.value();
    qBtnStart.setEnabled(!qTimer.isActive() && count > 0);
    qBtnStop.setEnabled(qTimer.isActive());
  };
  updateBtns();
  // install signal handlers
  QObject::connect(&qTimer, &QTimer::timeout,
    [&]() {
      qEditTimer.setValue(qEditTimer.value() - 1); // count down
    });
  QObject::connect(&qEditTimer, (void (QSpinBox::*)(int))&QSpinBox::valueChanged,
    [&](int count) {
      if (count <= 0) qTimer.stop();
      updateBtns();
    });
  QObject::connect(&qBtnStart, &QPushButton::clicked,
    [&](bool) { qTimer.start(); updateBtns(); });
  QObject::connect(&qBtnStop, &QPushButton::clicked,
    [&](bool) { qTimer.stop(); updateBtns(); });
  // runtime loop
  return app.exec();
}

testQTimerStartStop.pro : testQTimerStartStop.pro

SOURCES = testQTimerStartStop.cc

QT += widgets

Build and run: 构建并运行:

$ qmake-qt5 testQTimerStartStop.pro

$ make && ./testQTimerStartStop
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQTimerStartStop.o testQTimerStartStop.cc
g++  -o testQTimerStartStop.exe testQTimerStartStop.o   -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread 
Qt Version: 5.9.4

testQTimerStartStop快照(动画)

Moving the QTimer to a different thread would add a lot of overhead. QTimer移到另一个线程会增加很多开销。 Any access to the QTimer had 任何对QTimer访问都可以

  • to happen before starting the thread or 在启动线程之前发生或
  • to be mutex guarded or 被互斥保护
  • to be done through signals (with Qt::QueueConnection ). 通过信号来完成(使用Qt::QueueConnection )。

I considered it for a moment to adapt my sample respectivley but soon realized the necessary effort and stopped. 我考虑了一会儿以适应我的样本方面,但很快意识到了必要的努力并停止了。 IMHO, I wouldn't recommend this unless there is a good reason to do so. 恕我直言,除非有充分的理由,否则我不建议您这样做。

Please, consider that: An application which is under heavy load which causes significant delays of timeout signal emitting is probably not able as well to handle timeout events which are emitted by another thread in time. 请考虑以下事项:一个负载过大的应用程序会导致严重延迟超时信号的发出,因此该应用程序可能无法很好地处理另一个线程及时发出的超时事件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM