0

これは、QThread のサブクラスの run メソッドです。

void crono::Controller::run() {

    //initialise timer
    int *i = & this->model->seconds_elapsed;

    for (*i = 0; *i < this->model->seconds_total; (*i)++) {

    //calculate current seconds/minutes/hours elapsed starting  from seconds_elapsed (*i)
    this->model->tick(); 

    //should display in the form the time elapsed
    this->vista->showTime(); 
    sleep(1000);


    }

    Beep(1000, 500); //beep when all is over

}

コントローラーはモデル値を更新します。

QT フォームは開始時に開かれます。メイン アプリケーション スレッドにあると思います。

問題は、despise on debug *i=0 および seconds_total = X > 0 であり、ループが 1 回だけ実行され、最初にデバッグが停止した後 (終了しない)、フォームがポップアップしますが、何も起こりません。

私が推測できる唯一のことは、コントローラースレッドが優先順位を失い、二度とCPUを獲得できないことです。

どうすればこれを回避できますか?

EDIT QTimer を使用しようとしていますが、運が悪いです。

私はアップデートをパブリックスロットとして宣言し、次のように実装しました:

void crono::Controller::update() { 

    this->modello->tick();
    this->vista->showTime();

    //eventually stop at some point (pointer to timer and timer->stop()? 
    //...
    //Beep(1000, 500);
}  

そして、ループ サイクルの代わりにコントローラー (スレッド) オブジェクトに QTimer を挿入しました。

void crono::Controller::run() {

    //inizializzo timer
    int *i = & this->modello->secondi_trascorsi;

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()),this, SLOT(update()));
    timer->start(1000);


}

理由はわかりませんが、update() メソッドが無限に呼び出されるのではなく、まったく呼び出されません。なんで?

4

4 に答える 4

6

よくある混乱はQThread、独自の別のスレッドで実行されることです。これはそうではありません; 代わりに、QThreadそれが制御する子スレッドでイベント ループを開始します。QThread簡単に呼び出すことができますQThreadManager

QThreadつまり、作成している機能は (処理するスレッドではなく) メイン スレッドに存在するため、 をサブクラス化しないでくださいQThread。シグナルに接続されたスロットを持つ QObject サブクラスを作成しますstarted()。次に、インスタンスを使用しmoveToThread()て呼び出します。run()QThread

また、子スレッドからメイン スレッド関数を直接呼び出すことはできません。ダイアログ ボックスを表示するには、メイン スレッド内のオブジェクトへのキュー接続シグナルが必要です。

于 2015-04-02T14:15:35.383 に答える
3

Tim Meyer がコメントで指摘したように、シグナル/スロット メカニズムが機能するために必要なスレッドのイベント ループを開始するにQThread:exec()は、実装の最後に呼び出す必要があります。QThread::run()

しかし、あなたはそれを間違っているようです。

于 2013-02-06T13:51:45.617 に答える
2

まず第一に、QThreadほとんどの理由で継承されることは想定されていません。

通常、スレッド化は次のように行われます: http://qt-project.org/doc/qt-4.8/QThread.html#details

スレッドで時間をカウントし、一定期間後に何かを実行するだけでよい場合は、QTimer代わりにQTimer::timeout()信号をスロットに接続して経過時間を表示することができます。

于 2013-02-06T09:38:54.270 に答える
1

あなたのループは次のようになるはずです:

//initialize timer
int elapsed = this->model->seconds_elapsed;

for (int i = 0; i < elapsed; i++) 

ポインターを使用する必要はないと思います。複雑にしないでおく。

これでもうまくいかない場合は、何か別のことをしている可能性があり、コードからは明らかではありません。

また、スレッド シグナリングは を使用して行われませんsleep。スレッド シグナルの目的で、セマフォや条件変数などのスレッド イベントを調べる必要があります。

値を定期的に更新したい場合は、QTimer を使用してみませんか?

sleep有効な用途はほとんどなく、睡眠を必要としない問題を解決していると確信しています。

于 2013-02-06T09:32:56.453 に答える