背景: 在我们的嵌入式QT应用程序(基于ARM处理器)中,有一个Qtimer每20ms就会超时。 更新用户界面对象是在该计时器的超时处理程序内完成的。
此外,我们还有一个计算量很大的任务,我将其替换为一个“for”循环,其中包含大约 3000 次迭代和打印语句,以便于理解。 我在此操作期间显示 BusyIndicator。
问题1: 当显示 BusyIndicator 时,设置为 20ms 的 Qtimer 每 40 秒以上就会超时。(无论如何,此时这不会引起任何问题,因为显示 BusyIndicator 时不会执行任何与 UI 相关的操作)。
问题2(实际问题): 一旦繁重的任务完成,BusyIndicator 就会被禁用。禁用 BusyIndicator 后触发的 Qtimer 第一次也需要 40 秒以上才超时,然后它会恢复并随后每 20 毫秒触发一次。 因此,一旦禁用 BusyIndicator 并显示任何有效页面,UI 将在 40 秒以上的时间内没有响应。
问题:
注: 我在 QtCreator 中创建了一个虚拟项目,并创建了一个基于演示桌面的应用程序(在 Windows 和 Ubuntu 中),具有相同的场景(即 QTimer 被阻塞的繁重任务中断了一段时间),我看不到任何问题(QTimer 立即触发)阻塞任务完成后)。请在下面找到模拟我的问题场景的演示应用程序的代码:
main.cpp
#include "main.h"
myClass *classPtr;
static int loopStart=0;
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
myClass classs;
classPtr = &classs;
return app.exec();
}
myClass::myClass(QObject *parent):
QObject(parent)
{
timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &myClass::timerEvnt);
timer->start(20);
}
void myClass::timerEvnt()
{
myClass::looop();
if(loopStart >= 5)
qDebug()<<"timer continuation";
loopStart++;
}
void myClass::looop()
{
int j=0;
if(loopStart == 5)
{
for(int i=0; i<300;i++)
{
qDebug()<<"iterations="<<i;
}
qDebug()<<"#####################for loop comp="<<j;
}
}
main.h
#ifndef MAIN_H
#define MAIN_H
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QObject>
#include <QTimer>
#include <QQuickView>
#include <QElapsedTimer>
class myClass : public QObject
{
Q_OBJECT
public:
QTimer *timer;
explicit myClass(QObject* parent = nullptr);
void timerEvnt();
void looop();
};
#endif // MAIN_H
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Rectangle {
width: parent.width
height: parent.height
Text {
id: displayText
anchors.centerIn: parent
text: "Initial Message"
font.pixelSize: 20
}
}
}
提前致谢
考虑以下代码。在这里,无论平台如何(可以是 intel PC,可以是嵌入式 ARM 平台),我们保证
Timer
代码只会利用 QML 引擎的 50%,从而允许 QML 引擎赶上自己的事件。
如果您阅读代码,它将以 200 毫秒的间隔安排一次
Timer
,并且 onTriggered
的实现上限为 100 毫秒。因此,我们 50% 的时间都在回馈 QML 引擎。执行的迭代次数因平台而异,但是,我们保证此代码是跨平台友好的。
import QtQuick
import QtQuick.Controls
Page {
property double calcPI: 4
property int div: 1
property int totalIter: 0
Text {
text: "%1 (%2 total iterations)".arg(calcPI.toString()).arg(totalIter)
}
Timer {
interval: 200
repeat: true
running: true
onTriggered: {
let start = Date.now();
while (Date.now() - start < 100)
calcStep();
}
}
function calcStep() {
div += 2;
calcPI -= 4 / div;
div += 2;
calcPI += 4 / div;
totalIter++;
}
}
您可以在线尝试此代码!