Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Как проверить, есть ли в цикле событий ожидающие события вне потока?

Автор вопроса: AlexPОтветов: 1

Вызов QCoreApplication::hasPendingEvents() или QAbstractEventDispatcher::instance()->hasPendingEvents() внутри потока работает нормально. Однако вне его последний (с соответствующим параметром) всегда возвращает false (первый нельзя использовать снаружи, потому что он относится к потоку, из которого он вызывается).

Вот полный код:

#include <QCoreApplication>
#include <QAbstractEventDispatcher>
#include <QThread>
#include <QDebug>

bool hasPendingEvents(QThread *thread = 0) {
  return QAbstractEventDispatcher::instance(thread)->hasPendingEvents();
}

class MyObject: public QObject {
  Q_OBJECT

public slots:
  void Run() {
    qDebug() << __LINE__ << hasPendingEvents() << QCoreApplication::hasPendingEvents();
    QThread::sleep(1);
  }
};

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

  QThread thread;
  MyObject t;
  t.moveToThread(&thread);
  thread.start();
  for (int i = 0; i<4; ++i) QMetaObject::invokeMethod(&t, "Run", Qt::QueuedConnection);

  for (int i = 0; i<10; ++i) {
    QThread::msleep(500);
    qDebug() << __LINE__ << hasPendingEvents(&thread) << hasPendingEvents(t.thread());
  }
  return 0;
}

#include "main.moc"

Вот результат:

15 true true
31 false false
31 false false
15 true true
31 false false
31 false false
15 true true
31 false false
31 false false
15 false false
31 false false
31 false false
31 false false
31 false false

Почему QAbstractEventDispatcher.hasPendingEvents() не работает вне потока? Может есть альтернатива?

  • Обратите внимание, что &thread == t.thread(), поэтому нет смысла проверять одно и то же дважды. Kuba hasn't forgotten Monica 31.01.2014

multithreadingqtevent-loopqt5qthread

Ответы

Ответ 1 · рейтинг 2 · Kuba hasn't forgotten Monica

То, что вы показываете, может быть ошибкой Qt. Увы, вам может не понадобиться проверять таким образом, есть ли в другом потоке ожидающие события.

Единственная причина, по которой я вижу, что вы можете захотеть это сделать, - это управлять своим собственным пулом потоков и перемещать объекты в потоки, которые не "заняты". Вы бы сохранили список "занятых" и "доступных" потоков. Вот для чего нужен сигнал QAbstractEventDispatcher::aboutToBlock. Ваш пул потоков должен подключаться к этому сигналу для каждого потока, который он создает, и добавлять поток в "доступный" список при получении.

Если, с другой стороны, вы пытаетесь использовать его для реализации некоторого сжатия событий, это действительно самый неудобный способ сделать это. В другом ответе я показываю, как реализовать сжатие пользовательских событий, а также как сжимать вызовы сигнальных слотов.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы