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

Вызов 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() не работает вне потока? Может есть альтернатива?


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


Ответы (1)


arrow_upward
2
arrow_downward

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

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

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

person Kuba hasn't forgotten Monica    schedule 31.01.2014
comment
@AlexP Итак, Тьяго согласен с моей догадкой: вам действительно не следует так поступать. Хочешь разглашать, зачем тебе это нужно? Это действительно не должно быть необходимо. У меня никогда не было в этом необходимости. - person Kuba hasn't forgotten Monica; 04.02.2014
comment
Я работаю над задачей, состоящей из множества более мелких и похожих подзадач. Основная задача может быть обновлена ​​(следовательно, подзадачи должны быть отменены и перезапущены), а также результат каждой подзадачи должен быть передан в основной поток. Итак, как вы предположили, с помощью hasPendingEvents() я хотел сделать уродливое сжатие событий. Я знаю, что QtConcurrent существует, но его будущее представляется неопределенным: stackoverflow.com/a/19973345/796120 - person AlexP; 04.02.2014