これは私の最初の投稿であり、私の問題の解決策を見つけたいと思っています。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、またはカーネルのせいにしないでください。もう 1 つの奇妙な点は、QApplication の代わりに QCoreApplication を使用すると、問題なく動作することです。さらに、ubuntu ベースのマシンで同じコードを使用しており、QApplication で正常に動作します。これはMacでのみ発生すると思います(ただし、Windowsは試していません)。
QThread、QTimer、または QTimer::singleShot の使用を提案しないでください。私は最初にそれらを使用していましたが、同じ問題を抱えていました。私は QTimer と QThread でシグナルを使用していましたが、問題はシグナルが時間内に送信されなかったか、信号が時間内に送信されたがスロットが時間内に呼び出されなかったことです。待ち時間は同様でした (6 ~ 12 秒)。実際、それが私がc++スレッドを使用している理由です。なぜなら、c++スレッドを使用すると問題が解決するかもしれないと思ったのですが、そうではなかったからです。
どんな助けでも大歓迎です。
OS: 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 を使用するときに ui があると Mac が認識しているためです。したがって、アプリがアクティブでない場合、Mac はアプリをスリープ状態にすることができます。
回避策は、アプリの昼寝をプログラムで無効にすることでした。C/C++ で api を見つけることができませんでしたが、このリンクの目的の 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 を呼び出します。
これで私の問題は解決しました。