0

これは私の最初の投稿であり、私の問題の解決策を見つけたいと思っています。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 を呼び出します。

これで私の問題は解決しました。

4

1 に答える 1

2

ここで説明されている問題によく似ているように思えます。この場合、Apple の省電力「タイマー結合」(10.9 で導入されたようです) を無効にする解決策が役立つ場合があります。

(QApplication が特に問題を引き起こしている場合、その C++ ウィジェットのサポートが、Mac の Grand Central Dispatch に更新する必要がある古い Mac API を呼び出している可能性があります。最近の Qt を使用している場合は、5.5 ベータ版を試してみましたか?これは、バグ レポートを提出する価値があるかもしれません. しかし、実際には、特に「新しいアプリケーション」の場合、QGuiApplication の C++ ウィジェットと QtQuick UI の素晴らしい世界を捨てることを検討する必要があります)。

于 2015-06-06T22:48:12.117 に答える