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就触发一次??
关闭应用程序时多次出现错误“QObject::startTimer: QTimer can only be used with threads started with QThread”