Qt Gui не обновляется из-за проблем с потоками

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

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

Я посмотрел на похожие вопросы (например, Qt Splash Screen не отображается), но, кажется, ничто не решает мою проблему. Я попытался загрузить пустой QPixmap и просто дать ему сплошной цвет. Это тоже не появляется.

QApplication a(argc, argv);
QPixmap pxl("icon.bmp");
QSplashScreen qss(pxl);
qss.show();
qss.showMessage(QString::fromStdString("Please wait... Loading"));
a.processEvents();

MainWindow w;
//thread is blocked
w.preLoad();//this is where the lengthy process takes place
w.show();

qss.finish(&w);

Я хотел бы убедиться, что он хотя бы разок закрасит, прежде чем начать процесс загрузки.

------------------------РЕДАКТИРОВАТЬ------------------------- ------

Позвольте мне повторить, что вызов preLoad БЛОКИРУЕТ поток. Это не вариант. Я пробовал отдельный поток для этого процесса. Я попытался с отдельной темой для заставки (включение и последующее завершение, когда другой поток завершен). Я попытался использовать семафор между двумя потоками для достижения этой цели, и хотя все работает (включая заставку), для загрузки требуется 200-800 секунд. Это просто не приемлемо. Таким образом, я хотел бы посмотреть, есть ли что-то подобное с этой точки зрения.

-------------------------Окончательное решение----------------------- ---------

Благодаря комментариям, приведенным ниже, я узнал, что Qt имеет свою собственную функциональность потоков. Кажется, все проблемы, которые я видел, были вызваны взаимодействием std::thread и собственной реализации Qt.

У меня есть частичное решение, которое работает. Это не так аккуратно, как могло бы быть, но я хотел включить его в ветку вопросов.

//in the main method code described above
MainWindow w;
w.preLoad();
while(w.IsLoading())
{
  //waiting on semaphore signaling loading is complete
  //this part could probably be done better with QThread 
  //and signals, but it is a quick fix for now
  std::this_thread::sleepfor(std::chrono::milliseconds(500));
  a.processEvents();
}
w.show();

qss.finish(&w);


//In the MainWindow class
void MainWindow::preLoad()
{
  loading=true;//semaphore to stall main thread
  QFuture<void> future = QtConcurrent::run(this, &MainWindow::LongMethod);
}

void MainWindow::LongMethod()
{
  thirdPartyLibrary.impossibleCall();
  loading=false;//this handles my semaphore
}

1 ответ

Решение

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

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

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

Если вы хотите обновить представление GUI информацией, сгенерированной в другом потоке, рекомендуется использовать сигналы и слоты или использовать QtConcurrent.

Нить GUI и рабочая нить

Как уже упоминалось, каждая программа имеет один поток при запуске. Этот поток называется "основным потоком" (также известным как "поток GUI" в приложениях Qt). Графический интерфейс Qt должен работать в этом потоке. Все виджеты и несколько связанных классов, например, QPixmap, не работают во вторичных потоках. Вторичный поток обычно называют "рабочим потоком", потому что он используется для выгрузки обработки обработки из основного потока.

Другой способ - принудительно обновить графический интерфейс для этого, мы можем использовать qApp-> processEvents ().

Рекомендации:

Другие вопросы по тегам