У меня есть QDialog в моем основном потоке, и у меня есть некоторая логика, которая происходит в отдельном потоке. Когда логика начинается, подается сигнал, связанный с show () в диалоговом окне. Когда логика заканчивается, испускается сигнал, связанный с hide () в диалоге. Когда логика действительно работает, диалог отображается / скрывается правильно. Если логика «ничего не делает» и сигналы просто излучаются последовательно, диалог не всегда отображается / скрывается должным образом.
Мои соединения сделаны примерно так:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget* parent = 0) :
Ui(new Ui::MainWindowUi),
Transferer(new DataTransferer()),
TransferProgress(this),
TransferThread()
{
Ui->setupUi();
connect(&Transferer, SIGNAL(Begin()), &TransferProgress, SLOT(show()));
connect(&Transferer, SIGNAL(End()), &TransferProgress, SLOT(hide()));
Transferer.moveToThread(&TransferThread);
TransferThread.start();
Transferer.DoStuff(true);
}
virtual ~MainWindow()
{
TransferThread.quit();
TransferThread.wait(1000);
delete Ui;
Ui = NULL;
}
private:
Ui::MainWindowUi* Ui;
DataTransferer Transferer;
TransferProgressDialog TransferProgress;
QThread TransferThread;
}
Логика выглядит примерно так:
class DataTransferer : public QObject
{
Q_OBJECT
public:
DataTransferer(QObject *parent) : QObject(parent) {}
virtual ~DataTransferer() {}
void DoStuff(bool dontDoStuff)
{
emit Start();
if (!dontDoStuff)
{
QThread::sleep(1);
}
emit End();
}
}
Когда DataTransferer делает вещи, все работает нормально. Когда диалог отображается и скрывается в быстрой последовательности, я получаю диалоговое окно с призраками примерно каждый раз, когда вызываю DoStuff ().
Я использовал QThread :: currentThreadId () и убедился, что диалог и логика работают в разных потоках.
Почему мой диалог не скрывается должным образом в этом случае? Должен ли я просто заставить свою логику всегда работать по крайней мере несколько сотен миллисекунд (это решение плохо)? Есть ли способ, которым мой диалог может быть полностью загружен, прежде чем пытаться спрятаться? Должен ли я обрабатывать эти сигналы / слоты по-разному?
РЕДАКТИРОВАТЬ: я в настоящее время смирился с просто положить QThread :: sleep (1) после того, как я посылаю сигнал, чтобы показать () диалоговое окно. Мне не нравится это решение, но больше ничего не работает. Спящий режим (1) позволяет диалогу пройти весь путь до того, как его скрыть. Я также смог заставить это работать с QThread :: msleep (10), но это все равно привело к диалогу с призраком о 1 из 6 попыток.
Я пытался использовать член QMutex в логике диалога всякий раз, когда вызывал show () или hide (), но это не сработало.
Я изменил все межпоточные соединения, чтобы использовать Qt :: BlockingQueuedConnection и Qt :: QueuedConnection, и ни одна попытка не была успешной.
Я попытался переместить соединения слотов из диалогового окна в объект, который устанавливает соединения, а затем вызвал слоты напрямую, но это также не оказалось успешным.
Я думаю, что проблема возникает из-за того, что вызовы «show» и «hide» чередуются. Чтобы убедиться в этом, используйте семафор — заблокируйте объект, пока шоу не закончится, и дождитесь его в скрытии. Также посмотрите ответ с наибольшим количеством голосов здесь для другого возможного (возможно, лучшего) решения: подключение сигнала / слота в разных потоках между QObjects
использование Qt::BlockingQueuedConnection
подключать сигналы к слотам. Убедитесь, что цикл обработки событий основного потока не заблокирован. Кроме того, если ваш рабочий поток использует много процессорного времени — вы можете позвонить QThread::yeldCurrentThread()
вызов.