QApplication是懒惰(或使其他线程在应用程序中懒惰) [英] QApplication is lazy (or making other threads lazy in the app)

查看:172
本文介绍了QApplication是懒惰(或使其他线程在应用程序中懒惰)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我的问题是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这里12秒差)
05.06.2015 16:44:24( - 24这里6秒差)
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 ++线程可以解决问题,但它没有。



任何帮助是赞赏。

OS:MAC OSX 10.9.5。



uname -a输出:


$ b b

  Darwin 13.4.0 Darwin内核版本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的原因是mac认为我有ui当我使用QApplication。所以当我的应用程序没有激活,然后mac可以让我的应用程序睡觉。



解决方法是通过程序禁用应用程序。我在C / C ++中找不到api,但是在链接。所以我只是从c ++中调用目标c。



有c头文件appnap.h:

  #ifndef __APP_NAP__ 
#define __APP_NAP__

#if!defined(__ cplusplus)
#define C_API extern
#else
#定义C_API外部C
#endif

C_API void disableAppNap();
C_API void enableAppNap();

#endif

然后有appnap.m:

  #includeappnap.h
#include< Foundation / Foundation.h>

静态id活动;

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。



这解决了我的问题。

解决方案

很多像这里中描述的问题,在这种情况下禁用Apple的省电计时器合并(显然在10.9中引入)的解决方案可能会对您有所帮助。



(如果QApplication导致问题,这可能是因为它的C ++部件支持调用一些旧的Mac API,真正需要更新到Mac的大中央调度。如果你在最近的Qt - 尝试5.5测试版? - 并且看到这一点,它可能是值得提交一个错误报告。但真的,特别是对于一个新的应用程序,你应该考虑为QGuiApplication和QtQuick UI的奇妙世界切开C ++小部件)。


This is my first post here and I hope to find a solution to my problem. I have started developing an app for Mac using Qt. I am facing a huge and frustrating problem right now.

My problem is QApplication event loop becomes lazy (or makes other threads lazy in the app) after 20-50 seconds. I tried to replicate the same problem and came up with the code below.

So here is what I do. I create a c++ new thread and the new thread prints the current time in every 2 seconds. The problem is after 10-30 iterations, some iterations take 6-12 seconds which shouldn't happen because I just sleep 2 seconds in every iteration. I ran the code below and the output is like this:

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$

When I run this program, every single time the same problem happens. I am not sure if the same problem will happen if someone else tries to do it. But it happens in my machine.

The code below without QApplication works fine. So please do not blame c++ thread or usleep or the kernel for thread management or so. The other strange thing is that when I use QCoreApplication instead of QApplication it works fine as well. In addition, I use the same code in ubuntu based machine and it works fine with QApplication. I guess this only happens in Mac (I haven't tried windows though).

Please do not suggest using QThread, QTimer or QTimer::singleShot. I was using them at first and having the same problem. I was using signals with QTimer and QThread and the problem was that signals were not emitted in time or signals emitted in time but the slots were not called in time. The latency was similar (6 - 12 seconds). Actually, that is why I am using c++ thread because I thought using c++ thread may solve the problem but it didn't.

Any help is appreciated.

OS: MAC OSX 10.9.5.

uname -a output:

Darwin 13.4.0 Darwin Kernel Version 13.4.0:
root:xnu-2422.115.4~1/RELEASE_X86_64 x86_64

The Code: 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

EDIT:

I solved my problem thanks to timday. I was having the problem in the link that timday provided. It was the app nap that was making my app sleep so that is why I was having timer and sleep problems. The reason it only happens to QApplication but not to QCoreApplication is that mac thinks that I am having ui when I use QApplication. So when my app is not active then mac can put my app to sleep.

The workaround was to disable app nap programmatically. I couldn't find api in C/C++ for it but there is api in objective c in this link. So I just called objective c from c++.

Have c header file 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

Then have 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];
}

Add these lines to your .pro file:

HEADERS += appnap.h
OBJECTIVE_SOURCES += appnap.m
LIBS += -framework Foundation

Then when you don't want app nap to make your app sleep call disableAppNap before your operation begins and call enableAppNap after your operation ends.

This solved my problem.

解决方案

Sounds a lot like the problem described here, in which case the solution of disabling Apple's power-saving "timer coalescing" (apparently introduced in 10.9) may help you.

(If QApplication specifically causes the problem, it's possibly because its C++ widget support is calling some old Mac API which really needs to be updated to Mac's Grand Central Dispatch. If you're on a recent Qt - tried the 5.5 beta? - and seeing this, it might be well worth filing a bug report. But really, especially for a "new application" you should consider ditching the C++ widgets for QGuiApplication and the wonderful world of QtQuick UI).

这篇关于QApplication是懒惰(或使其他线程在应用程序中懒惰)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆