最近QTフレームワークを使い始めました。昨日、私は単純なマルチスレッドアプリケーションをプログラミングし始めました。現時点では、私は次の問題に多少なりとも取り組んでいます。Qtがイベントループをブロックしました
「重い計算」を行うためにスレッドを使用する2つのワーカークラスを考えてみましょう。最初のクラスFooWorkerは次のようになります。
class FooWorker : public QObject
{
Q_OBJECT
public:
FooWorker() : QObject() { }
~FooWorker() { }
signals:
void notify(int);
void aborted();
public slots:
void doWork()
{
int counter = 0;
forever {
// For the sake of this example this reassembles a heavy computational process
if(counter++ < 10) {
emit notify(counter);
QThread::sleep(1);
} else {
counter = 0;
// Wait until we get a signal to restart the process
mutex_.lock();
condition_.wait(&mutex_);
mutex_.unlock();
}
// We should check for a cancellation flag every iteration...
}
emit aborted();
}
private:
QMutex mutex_;
QWaitCondition condition_;
};
スロット 'doWork'は別のスレッドで実行するようにスケジュールされます。スロットは永遠に走り、10の通知が発せられるまで毎秒信号を発信しています。その後、もう一度目が覚めるまで待つ。
第二のクラス、BarWorkerは、次のようになります。
class BarWorker : public QObject
{
Q_OBJECT
public:
BarWorker() : QObject() { }
~BarWorker() { }
signals:
void aborted();
public slots:
void doWork()
{
forever {
// Another heavy computational process
QThread::sleep(1);
// We should check for a cancellation flag every iteration...
}
emit aborted();
}
void onNotify(int value)
{
qDebug() << "Notification value:" << value;
}
};
再びスロット「doWorkは」別のスレッドで実行するようにスケジュールされます。スロットは永遠に実行され、重い計算プロセスを実行します。再びプロセスが完了すると、私たちはそれが再び起き上がるまで待つ(この例のために、私はこのクラスでそれを残した)。
は最後のメインは、次のようになります。
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QThread* barThread = new QThread();
BarWorker* barWorker = new BarWorker();
barWorker->moveToThread(barThread);
QThread* fooThread = new QThread();
FooWorker* fooWorker = new FooWorker();
fooWorker->moveToThread(fooThread);
// Automatically deletes worker and thread
QObject::connect(fooThread, SIGNAL(started()), fooWorker, SLOT(doWork()));
QObject::connect(fooWorker, SIGNAL(aborted()), fooThread, SLOT(quit()));
QObject::connect(fooWorker, SIGNAL(aborted()), fooWorker, SLOT(deleteLater()));
QObject::connect(fooThread, SIGNAL(finished()), fooThread, SLOT(deleteLater()));
QObject::connect(barThread, SIGNAL(started()), barWorker, SLOT(doWork()));
QObject::connect(barWorker, SIGNAL(aborted()), barThread, SLOT(quit()));
QObject::connect(barWorker, SIGNAL(aborted()), barWorker, SLOT(deleteLater()));
QObject::connect(barThread, SIGNAL(finished()), barThread, SLOT(deleteLater()));
QObject::connect(fooWorker, SIGNAL(notify(int)), barWorker, SLOT(onNotify(int)), Qt::QueuedConnection);
fooThread->start();
barThread->start();
return a.exec();
}
私は、アプリケーションは何も実行しない
が印刷されます。これは、BarWorkerインスタンスのイベントループがブロックされているために予想されていました。 「通知」信号が放射されると、「onNotify」スロットはイベントキューに入れられます。 'doWork'スロットには決してループを終了しないので( '手動で中止するまで)、' onNotify 'スロットは呼び出されません。これを解決するために、私はつまり、物事のカップルを行うことができます。- はQtの:: DirectConnectionフラグを使用して「onNotify」スロットへの「通知」信号を接続します。これは、シグナルスレッド上で実行される通常の関数呼び出しのように見えます。
- 時々、QCoreApplication::processEvents()メソッドを呼び出して、イベントキューを強制的に処理します。
- 未知の解決策私は現時点では分かりません:)???
解決策の上にあるIMHOは多少醜いものであり、正しく感じられないので、誰かがこの問題の代替解決策を持っていることを望みます。
「永遠」とは何ですか? – HazemGomaa
Qtの無限ループ用です。http://doc.qt.io/qt-5/qtglobal.html#forever – Naidu
@PAVANCHANDAKAありがとう! – HazemGomaa