Подтвердить что ты не робот

Что я могу использовать, чтобы заменить сон и спать в моем приложении Qt?

Я импортирую часть существующего кода в свое приложение Qt и заметил там функцию сна. Я вижу, что этот тип функции не имеет места в программировании событий. Что мне делать вместо этого?

ОБНОВЛЕНИЕ: после мысли и обратной связи я бы сказал, что ответ: вызов сна вне основного потока графического интерфейса пользователя, и если вам нужно ждать в потоке графического интерфейса, используйте processEvents() или цикл событий, это предотвратит замораживание GUI.

4b9b3361

Ответ 1

Нет необходимости вообще разбивать события. Все, что мне нужно было сделать, это позвонить QApplication::processEvents(), где был sleep(), и это предотвращает замораживание GUI.

Ответ 2

Это не очень, но я нашел это в архивах Qt:

Метод сна QThread защищен, но вы можете разоблачить его так:

class SleeperThread : public QThread
{
public:
    static void msleep(unsigned long msecs)
    {
        QThread::msleep(msecs);
    }
};

Затем просто позвоните:

SleeperThread::msleep(1000);

из любого потока.

Однако более элегантным решением было бы реорганизовать ваш код на использование QTimer - это может потребовать сохранения состояния, чтобы вы знали, что делать, когда таймер отключается.

Ответ 3

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

//...
QMutex dummy;
dummy.lock();
QWaitCondition waitCondition;
waitCondition.wait(&dummy, waitTime);
//...

Ответ 4

Причина, по которой сон является плохой идеей в программировании на основе событий, заключается в том, что программирование на основе событий является фактически формой для неперехваченной многозадачности. Вызывая сон, вы запрещаете любое другое событие становиться активным и, следовательно, блокируете обработку потока.

В сценарии ответа на запрос для пакетов udp отправьте запрос и немедленно дождитесь ответа. Qt имеет хорошие API-интерфейсы сокетов, которые гарантируют, что сокет не будет блокироваться в ожидании события. Событие придет, когда оно появится. В вашем случае сигнал QSocket:: readReady является вашим другом.

Если вы планируете какое-то время планировать событие в будущем, используйте QTimer. Это гарантирует, что другие события не будут заблокированы.

Ответ 5

Я не знаю, как QT обрабатывают события внутренне, но в большинстве систем на самом низком уровне срок службы приложения выглядит следующим образом: основной код потока - это в основном цикл (цикл сообщения), в котором при каждом итерация, приложение вызывает функцию, которая дает ему новое сообщение; обычно эта функция блокируется, то есть, если нет сообщений, функция не возвращается и приложение останавливается.

Каждый раз, когда функция возвращается, приложение имеет новое сообщение для обработки, которое обычно имеет некоторый получатель (окно, которое отправлено), значение (код сообщения, например, указатель мыши был перемещен) и некоторые дополнительные данные (например, мышь была перемещена в координаты 24, 12).

Теперь приложение должно обработать сообщение; OS или GUI toolkit обычно делают это под капотом, поэтому с помощью некоторой черной магии сообщение отправляется получателю и выполняется правильный обработчик событий. Когда обработчик события возвращается, внутренняя функция, которая вызвала обработчик событий, возвращается, так же как и тот, который вызвал его и т.д., Пока элемент управления не вернется в основной цикл, который теперь снова вызовет функцию получения магического сообщения для получения другое сообщение. Этот цикл продолжается до тех пор, пока приложение не завершится.

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

Короче говоря: не используйте сон, если вам не нужно спать очень короткое время (всего несколько сотен миллисекунд), иначе графический интерфейс станет невосприимчивым. У вас есть несколько вариантов замены сон: вы можете использовать таймер (QTimer), но это может потребовать от вас много учета между событием таймера и другим. Популярной альтернативой является запуск отдельного рабочего потока: он будет обрабатывать только связь UDP и, будучи отделен от основного потока, не вызовет проблем при необходимости, если это необходимо. Очевидно, что вы должны позаботиться о защите данных, разделяемых между потоками, с помощью мьютексов и быть осторожными, чтобы избежать условий гонки и всех других проблем, возникающих при многопоточности.