Qt multi-threaded display synchronization problem
-
We developed an image processing and display program based on Qt. We use sub-threads for image processing and the main thread as UI display. In order to display synchronization, we use the Qt::BlockingQueuedConnection parameter when connecting the signal-slot. There are other threads that may overwrite the image data, so we use locks. code show as below:
class ProcessThread : public QThread { Q_OBJECT public: ProcessThread(QObject *parent = nullptr); void run() override { int i=0; while (1) { if(isQuit)break; mutex.lock(); QString filename=QString("/home/%1.bmp").arg((i++)%2000); data=imread(filename.toStdString()); //dosomthing... emit processCompleted(&data); mutex.unlock(); } } void setIsQuit(bool v){isQuit=v;} signals: void processCompleted(const Mat *data); private: bool isQuit=false; Mat data; QMutex mutex; };
class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr): QWidget(parent) { thread=new ProcessThread(); connect(thread,SIGNAL(processCompleted(const Mat *)), this,SLOT(processCompleted(const Mat *)),Qt::BlockingQueuedConnection); thread->start(); } ~Widget() { thread->setIsQuit(true); thread->quit(); thread->wait(); delete thread; } void paintEvent(QPaintEvent *event) override { Q_UNUSED(event) QPainter p(this); p.drawImage(QPoint(0,0),image); } private slots: void processCompleted(const Mat *data) { if(data!=nullptr) { if(data->channels()==1) { image=QImage(data->data, data->cols, data->rows, data->step, QImage::Format_Grayscale8); } else { image=QImage(data->data, data->cols, data->rows, data->step, QImage::Format_RGB888); } } else { image=QImage(); } repaint(); } private: QImage image; ProcessThread *thread; };
int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
1、When I exit the program, it will be stuck in thread->wait() in the ~Widget() function; it cannot continue to execute;
2、If I comment out thread->wait(); it will not get stuck when exiting, but it will prompt: "QMutex: destroying locked mutex" and "QThread: Destroyed while thread is still running" errors;
3、、If the Qt::BlockingQueuedConnection parameter is not used when connecting the signal-slot, the first problem above will not occur, but the display will not be synchronized.If BlockingQueuedConnection is not used, the processing thread will not be synchronized with the UI main thread, that is, the processing thread will not wait for the display refresh of the UI main thread, which will cause display confusion. So we need to display synchronization. And I put the image processing thread in the QtConcurrent framework, but it still deadlocks when wairForFinished().
How to achieve multi-threaded display synchronization without causing blocking? Thanks!
-
We developed an image processing and display program based on Qt. We use sub-threads for image processing and the main thread as UI display. In order to display synchronization, we use the Qt::BlockingQueuedConnection parameter when connecting the signal-slot. There are other threads that may overwrite the image data, so we use locks. code show as below:
class ProcessThread : public QThread { Q_OBJECT public: ProcessThread(QObject *parent = nullptr); void run() override { int i=0; while (1) { if(isQuit)break; mutex.lock(); QString filename=QString("/home/%1.bmp").arg((i++)%2000); data=imread(filename.toStdString()); //dosomthing... emit processCompleted(&data); mutex.unlock(); } } void setIsQuit(bool v){isQuit=v;} signals: void processCompleted(const Mat *data); private: bool isQuit=false; Mat data; QMutex mutex; };
class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr): QWidget(parent) { thread=new ProcessThread(); connect(thread,SIGNAL(processCompleted(const Mat *)), this,SLOT(processCompleted(const Mat *)),Qt::BlockingQueuedConnection); thread->start(); } ~Widget() { thread->setIsQuit(true); thread->quit(); thread->wait(); delete thread; } void paintEvent(QPaintEvent *event) override { Q_UNUSED(event) QPainter p(this); p.drawImage(QPoint(0,0),image); } private slots: void processCompleted(const Mat *data) { if(data!=nullptr) { if(data->channels()==1) { image=QImage(data->data, data->cols, data->rows, data->step, QImage::Format_Grayscale8); } else { image=QImage(data->data, data->cols, data->rows, data->step, QImage::Format_RGB888); } } else { image=QImage(); } repaint(); } private: QImage image; ProcessThread *thread; };
int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
1、When I exit the program, it will be stuck in thread->wait() in the ~Widget() function; it cannot continue to execute;
2、If I comment out thread->wait(); it will not get stuck when exiting, but it will prompt: "QMutex: destroying locked mutex" and "QThread: Destroyed while thread is still running" errors;
3、、If the Qt::BlockingQueuedConnection parameter is not used when connecting the signal-slot, the first problem above will not occur, but the display will not be synchronized.If BlockingQueuedConnection is not used, the processing thread will not be synchronized with the UI main thread, that is, the processing thread will not wait for the display refresh of the UI main thread, which will cause display confusion. So we need to display synchronization. And I put the image processing thread in the QtConcurrent framework, but it still deadlocks when wairForFinished().
How to achieve multi-threaded display synchronization without causing blocking? Thanks!
@hujh said in Qt multi-threaded display synchronization problem:
3、、If the Qt::BlockingQueuedConnection parameter is not used when connecting the signal-slot, the first problem above will not occur, but the display will not be synchronized.
Because you pass a pointer to data which you instantly overwrite with new data - what do you expect?
-
Hi,
Beside the memory management issue pointed by @Christian-Ehrlicher, can you explain what synchronization you are talking about ? Your code has a single worker thread and your GUI shows only the result.
You should rather take inspiration from the Mandelbrot example.