这是我在这里的第一篇文章,我希望能找到解决我问题的方法。我已经开始使用 Qt 为 Mac 开发应用程序。我现在面临着一个巨大而令人沮丧的问题。
我的问题是 QApplication 事件循环在 20-50 秒后变得懒惰(或使应用程序中的其他线程变得懒惰)。我试图重现同样的问题并想出了下面的代码。
这就是我所做的。我创建了一个 C++ 新线程,新线程每 2 秒打印一次当前时间。问题是在 10-30 次迭代之后,一些迭代需要 6-12 秒,这不应该发生,因为我在每次迭代中只睡 2 秒。我运行了下面的代码,输出是这样的:
sumits-air:UbiqMac_qt Jay$ ./run.sh
"05.06.2015 16:43:30"
"05.06.2015 16:43:32"
"05.06.2015 16:43:34"
"05.06.2015 16:43:36"
"05.06.2015 16:43:38"
"05.06.2015 16:43:40"
"05.06.2015 16:43:42"
"05.06.2015 16:43:44"
"05.06.2015 16:43:46"
"05.06.2015 16:43:48"
"05.06.2015 16:43:50"
"05.06.2015 16:43:52"
"05.06.2015 16:43:54"
"05.06.2015 16:43:56"
"05.06.2015 16:43:58"
"05.06.2015 16:44:00"
"05.06.2015 16:44:02"
"05.06.2015 16:44:04"
"05.06.2015 16:44:06" (- 06 here)
"05.06.2015 16:44:18" (- 18 here. 12 seconds difference)
"05.06.2015 16:44:24" (- 24 here. 6 seconds difference)
"05.06.2015 16:44:26"
"05.06.2015 16:44:28"
"05.06.2015 16:44:30"
^C
sumits-air:UbiqMac_qt Jay$
当我运行这个程序时,每次都会出现同样的问题。我不确定如果其他人尝试这样做是否会发生同样的问题。但它发生在我的机器上。
下面没有 QApplication 的代码工作正常。所以请不要责怪 c++ 线程或 usleep 或内核进行线程管理等。另一件奇怪的事情是,当我使用 QCoreApplication 而不是 QApplication 时,它也能正常工作。此外,我在基于 ubuntu 的机器上使用了相同的代码,它与 QApplication 一起工作得很好。我想这只发生在 Mac 中(不过我还没有尝试过 Windows)。
请不要建议使用 QThread、QTimer 或 QTimer::singleShot。我一开始使用它们时遇到了同样的问题。我在 QTimer 和 QThread 中使用信号,问题是信号没有及时发出或信号及时发出但槽没有及时调用。延迟时间相似(6 - 12 秒)。实际上,这就是我使用 C++ 线程的原因,因为我认为使用 C++ 线程可能会解决问题,但事实并非如此。
感谢任何帮助。
操作系统:MAC OSX 10.9.5。
uname -a 输出:
Darwin 13.4.0 Darwin Kernel Version 13.4.0:
root:xnu-2422.115.4~1/RELEASE_X86_64 x86_64
代码: main.cpp :
#include <QApplication>
#include <QDebug>
#include <QDateTime>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <thread>
void test() {
while(true) {
qDebug() << QDateTime::currentDateTime().toString("dd.MM.yyyy hh:mm:ss");
usleep(2000000);
}
}
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
std::thread *heartbeatThread = new std::thread(&test);
a.exec();
heartbeatThread->join();
return 0;
}
测试.pro:
QMAKE_CXXFLAGS += -std=c++11
QMAKE_CXXFLAGS += -stdlib=libc++
LIBS += -stdlib=libc++
QT += core gui widgets
TARGET = test
TEMPLATE = app
SOURCES += main.cpp
编辑:
感谢 timday,我解决了我的问题。我在 timday 提供的链接中遇到了问题。正是应用程序小睡让我的应用程序进入休眠状态,这就是我遇到计时器和 sleep 问题的原因。它只发生在 QApplication 而不是 QCoreApplication 的原因是 mac 认为我在使用 QApplication 时有 ui。因此,当我的应用程序未处于事件状态时,mac 可以让我的应用程序进入休眠状态。
解决方法是以编程方式禁用应用程序 nap。我在 C/C++ 中找不到它的 api,但是在这个 link 中的 objective-c 中有 api .所以我只是从 C++ 中调用了 objective c。
有c头文件appnap.h:
#ifndef __APP_NAP__
#define __APP_NAP__
#if !defined(__cplusplus)
#define C_API extern
#else
#define C_API extern "C"
#endif
C_API void disableAppNap();
C_API void enableAppNap();
#endif
然后有appnap.m:
#include "appnap.h"
#include <Foundation/Foundation.h>
static id activity;
void disableAppNap() {
activity = [[NSProcessInfo processInfo] beginActivityWithOptions:NSActivityLatencyCritical | NSActivityUserInitiated
reason:@"Disable App Nap"];
}
void enableAppNap() {
[[NSProcessInfo processInfo] endActivity:activity];
}
将这些行添加到您的 .pro 文件中:
HEADERS += appnap.h
OBJECTIVE_SOURCES += appnap.m
LIBS += -framework Foundation
然后当你不想让app nap让你的app休眠时,在你的操作开始前调用disableAppNap,在你的操作结束后调用enableAppNap。
这解决了我的问题。
最佳答案
听起来很多像描述的问题here , 在这种情况下 solution禁用 Apple 的省电“计时器合并”(显然在 10.9 中引入)可能对您有所帮助。
(如果 QApplication 具体导致问题,可能是因为它的 C++ 小部件支持正在调用一些旧的 Mac API,这确实需要更新到 Mac 的 Grand Central Dispatch。如果您使用的是最近的 Qt - 尝试过 5.5 beta? - 看到这一点,可能值得提交 bug report。但实际上,尤其是对于“新应用程序”,您应该考虑放弃 QGuiApplication 的 C++ 小部件和 QtQuick UI 的精彩世界)。
关于c++ - QApplication 是懒惰的(或使应用程序中的其他线程懒惰),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30686488/