我一直在开发一个简单的对话框小部件,它应该以 10 Hz 的速率显示 GMT 时间。由于我正在使用的系统运行了很多天,它应该是稳定的。
在一些夜间运行中,我注意到我的“BAR”程序在执行几个小时后以 100% 的速度运行。我很困惑为什么会发生这种情况,但我已经能够将其范围缩小到三个函数:
我使用一个名为 ace_time
的简单函数来获取一天中的时间:
inline double ace_time(void)
{
struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz);
return (double) tv.tv_sec + 1e-6 * (double) tv.tv_usec;
}
然后我从这个函数的返回中获取毫秒、秒、分钟等。然后我使用 QTime
对其进行格式化:
QTime time(hours, minutes, seconds, milliseconds);
QString timeStr = time.toString("hh:mm:ss.zzz");
然后在我的标签中设置文本:
clock->setText(timeStr);
我很困惑为什么我会获得 100% 的 cpu 使用率,除非 gettimeofday
、QTime
或 setText
正在做我正在做的事情不期待。
这里的专家是否注意到这些函数有任何异常行为?
我正在使用 Qt 4.8,如果有帮助的话。
期待得到一些解决这个问题的想法。谢谢!
添加更多代码:
我想要两个酒吧。顶部和底部栏。所以我编写了一个 BarBase
类和一个 TopBar
类。我还需要编写一个自定义 QLayout 来帮助我进行布局。我非常怀疑布局管理器导致了这种情况,因为它仅在调整栏大小并且需要重新计算几何图形时调用。
class BarBase : public QWidget
{
public:
BarBase()
{
setFixedHeight(barHeight);
setContentsMargins(5, 0, 5, 0);
QPalette palette;
QColor color(50, 252, 50);
palette.setColor(QPalette::Background, color);
setAutoFillBackground(true);
setPalette(palette);
}
virtual ~BarBase();
protected:
QLabel *createWestLabel(const QString &);
QLabel *createCenterLabel(const QString &);
QLabel *createEastLabel(const QString &);
private:
QLabel *createLabel(const QString &, Qt::Alignment)
{
QLabel *label = new QLabel(str);
label->setAlignment(Qt::AlignVCenter | alignment);
//label->setFrameStyle(QFrame::Box | QFrame::Raised);
QFont font("Times");
font.setPixelSize(barHeight - 4);
font.setBold(true);
label->setFont(font);
return label;
}
};
这是我的仅用于 TopBar
的类(class)
class TopBar : public BarBase
{
Q_OBJECT
public:
TopBar()
{
Layout *layout = new Layout;
classification = createCenterLabel("Classification");
layout->addWidget(classification, Layout::Center);
hostname = createWestLabel("Hostname");
layout->addWidget(hostname, Layout::West);
layout->addWidget(createWestLabel(":"), Layout::West);
software = createWestLabel("Software");
layout->addWidget(software, Layout::West);
runMode = createEastLabel("SIM");
layout->addWidget(runMode, Layout::East);
layout->addWidget(createEastLabel(":"), Layout::East);
clock = createClockLabel("-dd::hh::mm::ss.z");
layout->addWidget(clock, Layout::East);
deadman = new QTimer;
connect(deadman, SIGNAL(timeout()), this, SLOT(updateLocalGMT()));
deadman->start(100); // 10 ms;
setLayout(layout);
setWindowTitle(tr("Top Bar"));
}
virtual ~TopBar();
public slots:
void updateLocalGMT()
{
double milliseconds = fmod(ace_time(), 86400.0) * 1000;
bool sign = (milliseconds >= 0.0);
if (!sign)
{
milliseconds = -milliseconds;
}
const int millisecondsToDays = 86400.0 * 1000.0;
const int millisecondsToHours = 3600.0 * 1000.0;
const int millisecondsToMinutes = 60 * 1000.0;
const int millisecondsToSeconds = 1000.0;
double days = floor(milliseconds / millisecondsToDays);
milliseconds -= days * millisecondsToDays;
double hours = floor(milliseconds / millisecondsToHours);
milliseconds -= hours * millisecondsToHours;
double minutes = floor(milliseconds / millisecondsToMinutes);
milliseconds -= minutes * millisecondsToMinutes;
double seconds = floor(milliseconds / millisecondsToSeconds);
milliseconds -= seconds * millisecondsToSeconds;
QTime time(hours, minutes, seconds, milliseconds);
/*
if (!time.isValid())
{
INFO("Invalid input to QTime [day, hour, min, sec, ms]: [%f %f %f %f %f]",
days, hours, minutes, seconds, milliseconds);
}
*/
QString timeStr = time.toString("hh:mm:ss.zzz");
timeStr = timeStr.left(timeStr.length() - 2); // to remove the last two z
timeStr.prepend((sign) ? "+" : "-");
timeStr.prepend("<code style='color:white'>");
timeStr.append("</code>");
// timeStr = timeStr.left(timeStr.length() - 2);
// qDebug() << currentTime;
clock->setText(timeStr);
}
private:
QLabel *classification;
QLabel *hostname;
QLabel *software;
QLabel *runMode;
QLabel *clock;
QLabel *createClockLabel(const QString &text)
{
QLabel *label = new QLabel(text);
label->setAlignment(Qt::AlignVCenter);
QFont font("Monospace");
font.setStyleHint(QFont::TypeWriter);
font.setFixedPitch(true); // enforces monospace
font.setPointSize(18);
font.setBold(true);
label->setFont(font);
int pixelWidth = label->fontMetrics().width(label->text());
label->setFixedWidth(pixelWidth);
return label;
}
QTimer *deadman;
};
最佳答案
如果您的线程繁忙,QTimer 可能会落后并排队许多通知 - 这将导致您的处理发生远远超出您的预期。
要解决此问题,您应该执行以下操作:
void timer_slot()
{
if diff(now - last_time) < timer_interval
return; // Timer has come in too early so don't do anything
last_time = now;
}
如果您想重现此情况,只需使用 sleep() 阻塞您的线程,您会注意到,在线程被阻塞时,计时器槽将被调用尽可能多的次数。
QTimer 文档指出:
“精度和计时器分辨率 计时器永远不会早于指定的超时值超时,并且不保证在指定的确切值处超时。在许多情况下,它们可能会延迟一段时间,具体取决于系统计时器的准确性。 定时器的准确性取决于底层操作系统和硬件。大多数平台支持 1 毫秒的分辨率,但在许多实际情况下,计时器的精度并不等于该分辨率。 如果 Qt 无法提供所请求的计时器点击次数,它将默默地丢弃一些。”
但我发现,如果线程被阻塞/繁忙,则在 Windows 7 x64 上情况并非如此。
关于c++ - gettimeofday、QTime 或 QLabel->setText 中 CPU 利用率为 100%,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18613736/