QTimer使用时,为啥stop以后start会有两个计时器同时运行呢,start多少次就有多少个

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QTimer使用时,为啥stop以后start会有两个计时器同时运行呢,start多少次就有多少个相关的知识,希望对你有一定的参考价值。

参考技术A 你肯定每次start的时候,重新绑定槽了。

为啥 QTimer::singleShot 在时间 1 而不是 0 阻塞我的主线程

【中文标题】为啥 QTimer::singleShot 在时间 1 而不是 0 阻塞我的主线程【英文标题】:Why does QTimer::singleShot block my main thread at time 1 but not 0为什么 QTimer::singleShot 在时间 1 而不是 0 阻塞我的主线程 【发布时间】:2016-04-04 11:52:31 【问题描述】:

我一直在调试一些代码,这些代码似乎在 GUI 不可见时锁定了主线程。我已将其剥离回以下代码 sn-p 并且我发现我的 QTimer::singleShot 实现存在问题。

为了复制问题,我将计时器设置为 1(毫秒),启动应用程序循环并将应用程序窗口发送到后台。最终,应用程序将停止运行,直到 UI 进入前台。

如果我将计时器设置为 0,那么无论主应用程序窗口位于何处,它都会完美运行,我已将循环大小增加到 400 万,没有问题。

我想我坚持的是,有什么区别

QTimer::singleShot(1, this, SLOT(emptyListOfAnotherObjects()));

QTimer::singleShot(0, this, SLOT(emptyListOfAnotherObjects()));?

为什么一个会阻塞主线程而不是另一个?

在不同的线程中运行这个循环是值得的,保持 GUI 独立,会导致同样的问题。

class AnotherObject : public QObject

    Q_OBJECT

public:
    AnotherObject();

    void process();

signals:
    void done();
;

namespace Ui 
class MainWindow;


class MainWindow : public QMainWindow

    Q_OBJECT

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

public slots:
    void start(bool);

private slots:
    void emptyListOfAnotherObjects();

    void delayEmptyOfAnotherObject();

private:
    QList<AnotherObject*> m_listOfAnotherObject;
    Ui::MainWindow *ui;
;

==

AnotherObject::AnotherObject()

    qDebug() << "CTOR AnotherObject" << this;


void AnotherObject::process()

    emit done();
    deleteLater();


//==

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)

    ui->setupUi(this);
    connect(ui->start, SIGNAL(clicked(bool)), this, SLOT(start(bool)));


MainWindow::~MainWindow()

    delete ui;


void MainWindow::start(bool)

    for(long i=0; i<40000; i++)
        m_listOfAnotherObject.append(new AnotherObject());
    

    emptyListOfAnotherObjects();


void MainWindow::emptyListOfAnotherObjects()

    if(m_listOfAnotherObject.isEmpty()) 
        qDebug() << "List empty, done.";
        return;
    

    AnotherObject* i = m_listOfAnotherObject.takeFirst();
    connect(i, SIGNAL(done()), this, SLOT(delayEmptyOfAnotherObject()));
    i->process();

    qDebug() << m_listOfAnotherObject.count();


void MainWindow::delayEmptyOfAnotherObject()

    QTimer::singleShot(1, this, SLOT(emptyListOfAnotherObjects()));

谢谢

更新:

对不起,应该补充说这是 OSX 上的 Qt 5.2。

【问题讨论】:

我尝试了您的代码,但无法重现您的问题。在 0 和 1 毫秒时一切正常。 “将应用程序发送到后台”是什么意思?我尝试了很多东西,但似乎运行流畅。 @aManFromOuterSpace - 你在什么平台上测试这个?如果您使用的是 OS X,可能是由于 app nap 一旦主窗口进入前台,我单击一个按钮开始循环,然后单击另一个打开的窗口,在我的例子中是 QtCreator,然后将该应用程序带到前台,我的应用程序转到后面。 我做了同样的事情。在带有 Qt 5.5.1、64 位的 Win10 上它可以工作! 作为documentation shows,您可以通过检查活动监视器来简单地测试这一点,启用“App Nap”列,以显示哪些进程处于此状态。 【参考方案1】:

App Nap 可能是导致此问题的原因。

我怀疑使用 invokeMethod 会在线程的事件队列中放置一条消息,从而防止应用程序打盹。相比之下,使用 QTimer 会等待并检查超时,因此一个空的事件队列将允许它进入小睡状态。

无论如何,可以在您的应用程序中禁用应用程序小睡,如 here 所述。

当您使用 Qt 时,您需要使用 .mm 文件来encapsulate the objective-c code。

【讨论】:

以上是关于QTimer使用时,为啥stop以后start会有两个计时器同时运行呢,start多少次就有多少个的主要内容,如果未能解决你的问题,请参考以下文章

QT中的Qtimer 里start(100)开始计时以后,timeout是只触发一次,还是说每到100ms就触发一次??

QT5 Thread线程

关闭应用程序时多次出现错误“QObject::startTimer: QTimer can only be used with threads started with QThread”

mysql重复start stop slave测试

为啥切片和范围上限是排他的?

qt 计时器自动刷新图片