Я не знаю, как QT обрабатывают события внутренне, но в большинстве систем на самом низком уровне жизнь приложения выглядит следующим образом: код основного потока в основном представляет собой цикл ( цикл сообщений ) в котором на каждой итерации приложение вызывает функцию, которая выдает ему новое сообщение; обычно эта функция блокирует, то есть если нет сообщений, функция не возвращается и приложение останавливается.
Каждый раз, когда функция возвращается, приложение получает новое сообщение для обработки, которое обычно имеет некоторого получателя (окно, в которое отправляется), значение (код сообщения, например, указатель мыши был перемещен) и некоторые дополнительные данные (например, мышь была перемещена в координаты 24, 12 ).
Теперь приложение должно обработать сообщение; ОС или инструментарий GUI обычно делают это изнутри, поэтому с некоторой черной магией сообщение отправляется получателю и выполняется правильный обработчик события. Когда обработчик события возвращается, внутренняя функция, которая вызвала обработчик события, возвращает то же самое, что и та, которая вызвала его и т. Д., Пока элемент управления не вернется в основной цикл, который теперь будет снова вызывать магическую функцию извлечения сообщений, чтобы получить другое сообщение. Этот цикл продолжается до тех пор, пока приложение не завершится.
Теперь я написал все это, чтобы вы поняли, почему сон плох в приложении GUI, управляемом событиями: если вы заметите, пока обрабатывается сообщение , никакие другие сообщения не могут быть обработаны , поскольку основной поток занят выполнением вашего обработчика событий, который, в конце концов, является просто функцией, вызываемой циклом сообщений. Таким образом, если вы переведите свой обработчик событий в спящий режим, цикл сообщений также перейдет в спящий режим, что означает, что приложение тем временем не будет получать и обрабатывать любые другие сообщения, включая те, которые заставляют ваше окно перекрашиваться, поэтому ваше приложение будет выглядеть " повесить "с точки зрения пользователя.
Короче говоря: не используйте сон, если вам не нужно спать очень короткое время (максимум несколько сотен миллисекунд), в противном случае графический интерфейс пользователя перестает отвечать на запросы. У вас есть несколько вариантов замены sleep s: вы можете использовать таймер (QTimer), но для этого может потребоваться сделать большую бухгалтерию между событием таймера и другим. Популярной альтернативой является запуск отдельного рабочего потока: он будет просто обрабатывать связь UDP и, будучи отделенным от основного потока, не будет вызывать проблем со сном в случае необходимости. Очевидно, что вы должны позаботиться о защите данных, передаваемых между потоками с помощью мьютексов, и быть осторожными, чтобы избежать условий гонки и других проблем, возникающих при многопоточности.