2016-05-02 10 views
3

メインスレッドで自分自身の更新機能を実行する方法が必要です。私はメインループが走るたびに私に印をつける信号を見つけることができませんでした。メインループのコード実行

これは間違っていますか?私たちがループ内で何かを実行したい場合、ユーザーコードをスレッドで実行させることはQtのことですか?

+3

ゼロタイムアウトタイマーは何:) –

+2

ためのものであるものですイベントループが実行されるたびに目を通したいのですか? UIがメインスレッドでそれを行うのが遅くなり、不必要にエネルギーが節約される –

+0

mainthreadでboost :: asio :: io_serviceポーリング関数を呼び出す必要があります。私はメインスレッドでIOを完了する必要があります。 – awpsoleet

答えて

8
QTimer::singleShot(0, []{/* your code here */}); 

これは実際のところです。 0msタイマーを使用すると、コードは次のイベントループ反復で実行されます。あなたが特定のオブジェクトはもう存在しない場合、コードは実行されませんを確認するには、コンテキストオブジェクトを提供します。

QTimer::singleShot(0, contextObj, []{/* your code here */}); 

これはwell documentedです。

ここでは例のためにラムダを使用しました。明らかに、コードが長い場合は、代わりにスロット機能を提供することができます。

あなたのコードは一度だけの代わりに、すべてのイベントループの反復で繰り返し実行させたい場合は、シングルショットモードではない通常のQTimer使用:

auto timer = new QTimer(parent); 
connect(timer, &QTimer::timeout, contextObj, []{/* your code here */}); 
timer->start(); 

(注:間隔がありますデフォルトでは0msに設定されているため、処理が完了するたびにQTimer::timeout()が出力されます)。

ここでは、この動作はdocumentedです。

実行されるコードが完了するのに時間がかかりすぎると、実行中にGUIがフリーズしてしまうことは、言うまでもないことです。また

+0

だから、私が正しく理解すれば、毎回コードを実行するたびにsingleShotを呼び出す必要があります。 これはひどく非効率的です。 – awpsoleet

+1

@awpsoleetこの場合、通常のQTimerを使用することができます。私は答えを更新しました。 –

+0

このコードは悲しいことに、QThreadで起動していないスレッドからはうまくいきません。「タイマはQThreadで起動したスレッドでのみ使用できます」 – LubosD

2

、あなたのコードは、イベントループを使用すると、キューに入れられた接続を介してスロットメソッド呼び出しを使用することができます実行するたびに実行したい場合:

class EvtLoopTicker : public QObject 
{ 
    Q_OBJECT 
public: 

    EvtLoopTicker(QObject *pParent = nullptr) 
     : QObject(pParent) 
    {} 

public slots: 

    void launch() 
    { 
     tickNext(); 
    } 

private slots: 

    void tick() 
    { 
     qDebug() << "tick"; 

     // Continue ticking 
     tickNext(); 
    } 

private: 

    void tickNext() 
    { 
     // Trigger the tick() invokation when the event loop runs next time 
     QMetaObject::invokeMethod(this, "tick", Qt::QueuedConnection); 
    } 

}; 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 

    EvtLoopTicker ticker; 
    ticker.launch(); 

    return a.exec(); 
}