2016-04-04 20 views
0

GUIが表示されていないときにメインスレッドをロックしていると思われるコードをデバッグしています。私は次のコードスニペットに戻しました。私はQTimer :: singleShotの実装の周りに問題が存在することを確認しました。QTimer :: singleShotは、時刻1でメインスレッドをブロックするが、0ではないのはなぜですか?

問題を再現するには、タイマーを1(ミリ秒)に設定してアプリケーションのループを開始し、アプリケーションウィンドウをバックグラウンドに送ります。最終的に、UIがフォアグラウンドに持ち込まれるまで、アプリケーションは停止します。

メインのアプリケーションウィンドウがどこにあるかにかかわらず、タイマーを0に設定すると、ループサイズが問題なく最大で400万も増えました。

私は私がである立ち往生しています何を推測、

QTimer::singleShot(1, this, SLOT(emptyListOfAnotherObjects()));

QTimer::singleShot(0, this, SLOT(emptyListOfAnotherObjects()));の違いは何ですか?

メインスレッドを他のスレッドよりもブロックするのはなぜですか?

このループを別のスレッドで実行する価値があるのは、GUIを分離しておくことで同じ問題が発生します。

class AnotherObject : public QObject 
{ 
    Q_OBJECT 

public: 
    AnotherObject(); 

    void process(); 

signals: 
    void done(); 
}; 

namespace Ui { 
class MainWindow; 
} 

class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    explicit MainWindow(QWidget *parent = 0); 
    ~MainWindow(); 

public slots: 
    void start(bool); 

private slots: 
    void emptyListOfAnotherObjects(); 

    void delayEmptyOfAnotherObject(); 

private: 
    QList<AnotherObject*> m_listOfAnotherObject; 
    Ui::MainWindow *ui; 
}; 

==

AnotherObject::AnotherObject() 
{ 
    qDebug() << "CTOR AnotherObject" << this; 
} 

void AnotherObject::process() 
{ 
    emit done(); 
    deleteLater(); 
} 

//== 

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow) 
{ 
    ui->setupUi(this); 
    connect(ui->start, SIGNAL(clicked(bool)), this, SLOT(start(bool))); 
} 

MainWindow::~MainWindow() 
{ 
    delete ui; 
} 

void MainWindow::start(bool) 
{ 
    for(long i=0; i<40000; i++){ 
     m_listOfAnotherObject.append(new AnotherObject()); 
    } 

    emptyListOfAnotherObjects(); 
} 

void MainWindow::emptyListOfAnotherObjects() 
{ 
    if(m_listOfAnotherObject.isEmpty()) { 
     qDebug() << "List empty, done."; 
     return; 
    } 

    AnotherObject* i = m_listOfAnotherObject.takeFirst(); 
    connect(i, SIGNAL(done()), this, SLOT(delayEmptyOfAnotherObject())); 
    i->process(); 

    qDebug() << m_listOfAnotherObject.count(); 
} 

void MainWindow::delayEmptyOfAnotherObject() 
{ 
    QTimer::singleShot(1, this, SLOT(emptyListOfAnotherObjects())); 
} 

おかげ

更新:

申し訳ありませんが、これはOSX上のQt 5.2であることを付け加えておく必要があります。

+0

あなたのコードを試しましたが、問題を再現できません。すべて0と1msでうまく動作します。あなたは「アプリをバックグラウンドで送る」ということはどういう意味ですか?私はたくさんのものを試しましたが、流暢に動くようです。 – Paraboloid87

+3

@aManFromOuterSpace - これはどのプラットフォームでテストしていますか? OS Xを使用している場合は、[app nap](https://developer.apple.com/library/mac/documentation/Performance/Conceptual/power_efficiency_guidelines_osx/AppNap.html) – TheDarkKnight

+0

のメインウィンドウが表示されます。フォアグラウンド私はループを開始し、別の開いているウィンドウ、私のケースではQtCreatorをクリックするボタンをクリックし、フォアグラウンドにそのアプリケーションを持って来て、私のアプリは後ろに行く。 – aManFromOuterSpace

答えて

1

App Napがこの問題の原因である可能性があります。

私は、invokeMethodを使用するとスレッドのイベントキューにメッセージが配置され、アプリの起動が妨げられている可能性があります。対照的に、QTimerを使用すると、タイムアウトを待ってチェックするので、空のイベントキューではナップ状態に入ることができます。

いずれにしても、hereのように、アプリケーション内からアプリのナップを無効にすることができます。

Qtを使用しているので、.mmファイルをencapsulate the objective-c codeに使用することをお勧めします。

関連する問題