QApplication是懒惰的(或者在应用程序中使其他线程变得懒惰)

时间:2015-06-06 18:56:57

标签: c++ multithreading macos qt qapplication

这是我在这里的第一篇文章,我希望找到解决问题的方法。我已经开始使用Qt为Mac开发应用程序。我现在面临一个巨大而令人沮丧的问题。

我的问题是20-50秒后QApplication事件循环变得懒惰(或使应用程序中的其他线程变得懒惰)。我试图复制同样的问题并提出下面的代码。

所以这就是我的工作。我创建了一个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;
}

test.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提供的链接中遇到了问题。应用程序小睡使我的应用程序睡眠,这就是为什么我有计时器和睡眠问题。它只发生在QApplication而不是QCoreApplication的原因是,当我使用QApplication时,mac认为我有ui。因此,当我的应用程序未处于活动状态时,mac可以让我的应用程序进入休眠状态。

解决方法是以编程方式禁用app nap。我无法在C / C ++中找到api,但在link中有目标c的api。所以我刚从c ++调用了目标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

然后,如果您不想让应用程序小睡让您的应用程序在操作开始之前调用disableAppNap,并在操作结束后调用enableAppNap。

这解决了我的问题。

1 个答案:

答案 0 :(得分:2)

声音很多就像here所描述的问题一样,在这种情况下,solution禁用了Apple的省电&#34;计时器合并&#34 ; (显然是在10.9中介绍的)可以帮助你。

(如果QApplication专门导致问题,可能是因为它的C ++小部件支持调用了一些真正需要更新到Mac的Grand Central Dispatch的旧Mac API。如果你是在最近的Qt上 - 尝试过5.5 beta? - 并且看到这一点,它可能值得归档bug report。但实际上,特别是对于一个新的应用程序而言,你应该考虑放弃C ++小部件用于QGuiApplication和QtQuick UI的精彩世界。