1

内部QEventLoopで関数を呼び出すQTimerを使用しているときに、最近これに遭遇しました

QTimer インスタンスがあるとします。

QTimer* timer = new QTimer;

コンストラクターのどこかでそれを開始すると、100msごとに1回刻み始めます

timer->start(100);

楽しい部分です。内部 QEventLoop を持つスロットに接続します。

void SlotFunction()
{
    qDebug() << "entered";
    QEventLoop loop;
    loop.exec();
}

このループがいかに馬鹿げているかはさておき、スロットの処理を終了することはなく、タイマーの後続のタイムアウトが実行キューにスタックし続けることがわかります。すべてが順調で、あるべき姿です。

本来あるべきでないことは次のとおりです。QEventLoop は、スロットが無意識にアイドル状態になっている間もアプリの応答性を維持するため、次のようなボタンとその clicked() スロットを作成できます。

void OnClicked()
{
    timer->start(100);
}

ここで行っていることは、基本的に現在のタイマー サイクルを再起動することであり、それ以下でもそれ以上でもありません。右?いいえ!この再起動後、SlotFunction は再び起動し、タイマーの再起動後のティックが実際にはそれ以前に発行された他のすべてのティックと等しくないことを示唆しています...

私の唯一の質問は: WTF ?! タイマーを手動で再起動すると、スロットの追加時間を入力できるようになるのはなぜですか? freenodeで聞いてみたのですが、「あるべき姿です」という返事しか返ってきませんでした。

4

1 に答える 1

3

私はこれを試しましたが、クリックするたびに別の「入力された」行が作成されます。

新しいイベントループでスタックしているため、メインのイベントループは別のイベントを処理できません。

これは、2 番目のスロットを実装し、このスロットをタイムアウト信号に接続すると、非常に簡単に確認できます。

  • maineventloop は、次の eventloop を呼び出して、それ以上キューに入れられたイベントを処理しないとスタックします。
  • タイマー自体もこれ以上イベントをキューに入れません。これは、キューに入れること自体がスタックしたメインイベントループで行われるためです。タイマーは独自のイベント ループでは実行されません (そのため、Qtimers は正確なタイマーではありません)。
  • ボタンがクリックされるとすぐに、新しいイベントループがタイマーをチェックして、イベントtimeout()を生成する必要があるかどうかを確認します。
  • 新しいイベントが処理されるとすぐに、再び別のイベントループに陥ります...
  • これは、アプリケーションを終了するまで続きます。
  • アプリケーションを終了すると、ループが反転し、ボタンをクリックして最初のスロットに遭遇したのと同じ頻度で 2 番目のスロットが呼び出されます。

コード:

#include <QDebug>
#include <QTime>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    timer = new QTimer;
    timer->setInterval(2000);
    connect(timer,SIGNAL(timeout()),this,SLOT(timerslot()));
    connect(timer,SIGNAL(timeout()),this,SLOT(timerslot2()));
    timer->start();
}

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

void MainWindow::on_pushButton_clicked()
{
    timer->start(2000);
}

void MainWindow::timerslot()
{
    qDebug()<<"In";
    QEventLoop loop;
    loop.exec();
}

void MainWindow::timerslot2()
{
    qDebug()<<"More";
}

開始時の出力:

In

クリックごとに出力:

In

3クリック後の出力:

In
In
In
In

アプリケーションを終了する出力:

In
In
In
In
More
More
More
More
于 2014-11-13T15:51:18.630 に答える