Qt задержка выполнения

Qt задержка выполнения

Вызов функции через очередь посредством сигнал/слотов или QMetaObject::invokeMethod() — это по сути декларация о намерении. Лишь когда контекст выполнения целевого потока перейдёт к перебору очереди событий, то только тогда запланированное действие (вызов функции) будет произведено.

Соответственно, если целевой поток занят какой-либо задачей и относительно редко просматривает очередь событий, то декларации на вызов функции будут накапливаться. Как только контекст выполнения целевого потока освободится и наконец перейдёт к очереди событий, то разом будут произведены все ранее запланированные вызовы функции. Чтобы этого избежать, необходимо минимизировать время нахождения контекста выполнения целевого потока во вне его очереди событий. Проще говоря, целевой поток вообще ничего не должен делать и должен находиться в постоянном ожидании, либо его работа должна быть сведена к выполнению минимума задач.

В основе вызова функции через очередь посредством сигнал/слотов или QMetaObject::invokeMethod() лежит создание и отправка объекта события QMetaCallEvent. В целевой поток объект события отправляется посредством метода QCoreApplication::postEvent(), у которого в свою очередь имеется аргумент приоритетности выполнения со значением по умолчанию Qt::NormalEventPriority. Чем выше приоритет события, тем ранее оно будет выполнено обработчиком в очереди событий. Разумеется при условии, что контекст выполнения целевого потока не отвлекается на длительное время с целью выполнения посторонних задач.

К сожалению, в Qt не предусмотрена возможность указывать приоритет выполнения событий, создаваемых посредством вызова сигналов. Также, не предусмотрено это и при вызове QMetaObject::invokeMethod(). Однако никто не мешает организовать свою реализацию той же техники, но на основе собственного типа событий.

Например, произвольное событие:

Q_GLOBAL_STATIC_WITH_ARGS(int, _g_event_type     , (QEvent::registerEventType()))  class IHateQtThreadsEvent : public QEvent {     public:         static QEvent::Type eventType() {             return static_cast<QEvent::Type>(*_g_event_type);         }          IHateQtThreadsEvent()             : QEvent(IHateQtThreadsEvent::eventType()) {} }; 

… можно отправлять из потока-источника обычным в Qt образом, но с указанием повышенного уровня приоритетности:

void run() {     ...     QCoreApplication::postEvent(receiver_obj         , new IHateQtThreadsEvent()         , Qt::HighEventPriority);     ... } 

Указатель «receiver_obj» — это произвольный наследник QObject, «живущий» в целевом потоке. Для него останется лишь добавить пользовательский обработчик событий:

class IHateQtThreadsObject : public QObject {     Q_OBJECT      protected:         virtual void customEvent(QEvent *event) {             if(event->type() == IHateQtThreadsEvent::eventType()) {                 // Аргументы для вызова функции могут быть переданы                 // в объекте события.                 iHateQtThreads(arg1, arg2, arg3);             }         } }; 



Источник: ru.stackoverflow.com


Добавить комментарий