Это мой первый пост здесь, и я надеюсь найти решение моей проблемы. Я начал разрабатывать приложение для 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 после вашего завершение работы.
Это решило мою проблему.
Ваш std :: thread не может быть перенесен системой, как вы думаете? Это проблема. Система не знает, что ваш совершенно пустой поток предназначен для выполнения и может дать или не дать ему кусочек времени. И те, кто предлагает вам использовать QTimer или другой таймер, конечно, мы правы. Если бы вы не смогли добиться нормального решения, чем проблема, связанная с тем, как вы это делаете. – AlexanderVX
1. Какую версию Qt вы используете? 2. Какое у вас оборудование? 3. Имеет ли смысл использовать QThread :: usleep (статический метод QThread)? – timday
Александр, если вы внимательно прочитали, я упомянул, что приведенный выше код отлично работает без qapplication. Другое дело, что тот же код отлично работает в ubuntu. Так что это определенно что-то связано с Mac. –