2015-06-06 7 views
0

Это мой первый пост здесь, и я надеюсь найти решение моей проблемы. Я начал разрабатывать приложение для Mac с помощью Qt. Сейчас я столкнулся с огромной и неприятной проблемой.QApplication является ленивым (или делает другие темы ленивыми в приложении)

Моя проблема: цикл событий 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; 
} 

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:

Я решил свою проблему благодаря тому, что был в тот же день. У меня возникла проблема в ссылке, предоставленной в тот же день. Это был сон приложения, который заставлял мое приложение спать, поэтому у меня были проблемы с таймером и сном. Причина, по которой это происходит только с QApplication, но не с QCoreApplication, заключается в том, что mac считает, что я использую ui, когда я использую QApplication. Поэтому, когда мое приложение неактивно, Mac может отключить мое приложение.

Обходной путь заключается в том, чтобы программно отключить приложение. Я не мог найти api в C/C++ для него, но в объекте c есть api в объекте c link. Поэтому я просто назвал цель 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.м:

#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 после вашего завершение работы.

Это решило мою проблему.

+0

Ваш std :: thread не может быть перенесен системой, как вы думаете? Это проблема. Система не знает, что ваш совершенно пустой поток предназначен для выполнения и может дать или не дать ему кусочек времени. И те, кто предлагает вам использовать QTimer или другой таймер, конечно, мы правы. Если бы вы не смогли добиться нормального решения, чем проблема, связанная с тем, как вы это делаете. – AlexanderVX

+0

1. Какую версию Qt вы используете? 2. Какое у вас оборудование? 3. Имеет ли смысл использовать QThread :: usleep (статический метод QThread)? – timday

+1

Александр, если вы внимательно прочитали, я упомянул, что приведенный выше код отлично работает без qapplication. Другое дело, что тот же код отлично работает в ubuntu. Так что это определенно что-то связано с Mac. –

ответ

2

Звучит много как проблемы, описанной here, в этом случае solution отключения энергосбережения «таймер коалесцирующего» Apple (по-видимому, введенных в 10.9) может помочь вам.

(Если QApplication вызывает определенную проблему, возможно, потому что его поддержка виджета C++ вызывает некоторый старый Mac API, который действительно нуждается в обновлении до Grand Central Dispatch от Mac. Если вы находитесь в недавнем Qt - попробовали бета-версию 5.5 ? - и, видя это, возможно, стоит записать bug report. Но на самом деле, особенно для «нового приложения», вы должны подумать о том, чтобы вырезать виджеты C++ для QGuiApplication и прекрасный мир QtQuick UI).

+0

Тираж, спасибо за ваш ответ. Теперь у меня нет мака. Я попробую решение завтра и опубликую результат здесь. Другое дело, что для решения требуются привилегии root. Это приложение будет использоваться клиентами и не может требовать доступа root. Знаете ли вы какое-либо другое обходное решение, которое не требует доступа root? Кроме того, я думаю, что проблема заключается в QApplication, потому что, как я сказал, если я использую QCoreApplication, он работает нормально. Я отправил письмо в Qt для обсуждения проблемы с ними. –

+1

Действительно, у меня была проблема в ссылке, которую вы предоставили. Я также прочитал [документ] (https://www.apple.com/media/us/osx/2013/docs/OSX_Power_Efficiency_Technology_Overview.pdf). Теперь я лучше понимаю, почему у меня проблема с QApplication, но не для QCoreApplication. В примере кода я использую QApplication, но у меня нет ничего, чтобы показать, поэтому приложение App Nap считает, что мне не нужно приложение, и иногда приложение спят дольше. Для QCoreApplication я предполагаю, что он считает, что приложение является фоновым приложением и позволяет выполнять свою работу. Хотя я не уверен. –

+0

Вы знаете больше о проблеме, чем сейчас. В основном я интересуюсь этой проблемой, потому что, хотя Qt стремится представить хороший общий API для различных платформ ... реалии и причуды этих платформ имеют привычку пробивать фасад. – timday

 Смежные вопросы

  • Нет связанных вопросов^_^