为什么QTimer::singleShot在时间1阻塞了我的主线程而不是0
Why does QTimer::singleShot block my main thread at time 1 but not 0
我一直在调试一些代码,当GUI不可见时,这些代码似乎锁定了主线程。我已经把它剥离到下面的代码片段中,并且我发现在我的QTimer::singleShot实现中存在一个问题。
为了复制这个问题,我将计时器设置为1(毫秒),启动应用程序循环,并将应用程序窗口发送到后台。最终,该应用程序将陷入停顿,直到用户界面进入前台。
如果我将计时器设置为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。
App Nap可能是导致此问题的原因。
我怀疑使用invokeMethod会在线程的事件队列中放置一条消息,从而防止应用程序打盹。相反,使用QTimer会等待并检查超时,因此空的事件队列将允许它进入小睡状态。
无论如何,可以从您的应用程序中禁用应用程序小睡,如下所述。
在使用Qt时,您需要使用一个.mm文件来封装objective-c代码。
相关文章:
- 线程之间的布尔停止信号
- 以线程安全的方式调用"QQuickPaintedItem::updateImage(const QImage&image)"(no QThread)
- 如何从线程中的不同模块调用函数?
- 我可以计算多线程数的平均值吗?
- 为什么我的 std::atomic<int> 变量不是线程安全的?
- 我怎么知道C++编译器是否制作线程安全的静态对象代码
- 睡眠:(睡眠或usleep)并没有将我的线程中的所有内容悬挂在Linux中,而是在Windows中悬挂吗?为什么
- 我可以在没有静音的线程中读取线程中的bool变量
- 当我从C#代码调用C++代码时,它是线程安全的吗
- 我需要保护一个由一个线程编写并由多个线程读取的变量吗
- 在 C++ 中易变:我是否应该定义一个可能被几个线程更改的变量作为易失性
- 对我来说,使 boost::statechart::state_machine 线程安全的最简单方法是什么?
- c ++ 为什么我的日期解析不是线程安全的
- 我知道 pantheios 是线程安全的,但它是进程间安全的吗?
- 多线程:我需要用只读方法保护我的变量吗
- 我可以挂起除一个线程外的进程吗?
- 我可以制作一个线程安全的 std::atomic<vector<int>>吗?
- 我如何使任何c++库都是线程安全的
- 我需要并行化或多线程我的应用程序
- 如果我只需要变量在其他线程中的值,我应该在一个线程中锁定变量吗?如果我不需要它为什么它有效?