Приложение QT зависает - PullRequest
1 голос
/ 22 июня 2019

Мы разработали систему, которая интегрируется с камерой и микроконтроллером.Графический интерфейс показывает изображение с камеры и счетчик последовательностей с микроконтроллера, мы использовали последовательный поток для опроса данных из микроконтроллера и посылали сигнал в графический интерфейс для его отображения, а также мы использовали отдельный поток для захвата изображения и передачи его на главныйнить.Проблема с приложением заключается в том, что когда система находится в режиме ожидания, графический интерфейс пользователя зависает, и мы вынуждены перезапустить приложение, чтобы начать работу (в режиме ожидания пользователь не арендует никаких кнопок и счетчиков, а изображения поступают непрерывно).Здесь важно отметить, что проблема замораживания графического интерфейса не является постоянной.Установлено несколько систем, а в некоторых местах проблема зависания (не отвечает) возникает один раз в 2/3 недели, а в некоторых местах - один раз в 2 дня.Ожидание ответа приложения не помогает.

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

1 Ответ

1 голос
/ 22 июня 2019

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

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

Как вы передаете данные из последовательных потоков и потоков камеры в поток GUI?Здесь, возможно, возникла проблема.

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

Вот несколько стратегий для безопасной передачи данных между потоками:

  1. Целое число является атомарным на уровне набора команд ЦП, поэтому вы можете безопасно читать и записывать целое число (или любой тип данных, равный или меньший, чем целое число, такой как bool, одиночный символ или указатель) из нескольких потоков без возникновения какого-либо противоречивого состояния.Вы должны объявить такие переменные с помощью шаблона std :: atomic <> в C ++, чтобы гарантировать, что компилятор не будет выполнять оптимизации, нарушающие атомарность.

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

  2. Сигналыи слоты в Qt поточно-ориентированы.Один из способов передачи сложных данных между потоками - это emit данные в одном потоке и slot в другом потоке, которые получают эти данные.Qt позаботится о любых проблемах параллелизма в этом случае.Единственное, что нужно здесь, - это если поток (и) потребителя данных не может достаточно быстро абсорбировать данные, очередь событий Qt будет заполнена слишком большим количеством данных, и в конечном итоге ваше приложение будет аварийно завершаться из-за новых событий графического интерфейса пользователя (таких как щелчки мыши,события перерисовки и т. д.) больше не могут проходить через забитую очередь событий.

  3. Вы можете использовать QMutex, чтобы гарантировать, что только один поток читает или записывает сложную структуру данных водин раз.QMutex позволяет блокировать / останавливать выполнение в одном или нескольких потоках, в то время как один поток «удерживает» мьютекс и позволяет ему выполнять работу с данными без риска того, что другие потоки коснутся этих данных.Когда этот поток завершается, он «освобождает» мьютекс, что позволяет одному из других потоков «удерживать» мьютекс, возобновляя его выполнение, чтобы он мог работать с данными.

Что касается тестирования, то, как правило, вероятность сбоя вашего приложения из-за нарушения параллелизма возрастает при увеличении скорости передачи данных.Если вы сможете искусственно увеличить частоту кадров камеры и «серийный счет», передаваемый потоку GUI, вы сможете быстрее воспроизвести сбой приложения.Как только вы успешно решите проблемы с параллелизмом, вы сможете заполнить систему данными и никогда не привести к сбою.

...