Недавно я начал использовать инфраструктуру QT. Вчера я начал программировать простое многопоточное приложение. На данный момент я несколько застрял в следующей проблеме.Цикл заблокированных событий Qt
Рассмотрите два рабочих класса, которые используют поток для выполнения «тяжелых вычислений». Первый класс, 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» не будет вызываться. Чтобы решить эту проблему, я могу сделать несколько вещей, а именно:
- Подключить сигнал «уведомлять» в слот «onNotify», используя флаг Qt :: DirectConnection. Таким образом, он выглядит как обычный вызов функции, выполняющийся в сигнальной нити.
- Иногда вызывайте метод QCoreApplication::processEvents(), чтобы заставить очередь событий обрабатываться.
- Неизвестное решение, которое я не знаю в это время:) ???
Я надеюсь, что у кого-то есть альтернативное решение этой проблемы или даже предлагается совершенно другой подход, потому что IMHO над решениями несколько уродливые и не чувствуют себя хорошо.
Что такое "навсегда"? – HazemGomaa
Это для бесконечных циклов в Qt http://doc.qt.io/qt-5/qtglobal.html#forever – Naidu
@PAVANCHANDAKA спасибо! – HazemGomaa