Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Shared Memory and Threads



  • Hi everyone !

    I'm trying to launch my application on 2 threads : 1 for reading and 1 for writing.
    On a gui, I have a slider (input) and a lcdNumber (output). I want the slider to write its value somewhere and, on another thread, read this same value to be displayed on the lcdnumber.

    Here is the code :

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QLCDNumber>
    #include <QSlider>
    #include <QThread>
    #include <QDebug>
    
    namespace Ui {
    class MainWindow;
    }
    
    template<typename T>
    class Obj : public QThread
    {
        virtual void run()=0;
    protected:
        int* _m;
        T* _s;
    public:
        Obj(T* s, int* m) : _m(m), _s(s){ }
    };
    
    class Slid : public Obj<QSlider>
    {
        void run() override;
    public:
        Slid(QSlider* s, int* m) : Obj<QSlider>(s,m) {}
    };
    
    class Lcd : public Obj<QLCDNumber>
    {
        void run() override;
    public:
        Lcd(QLCDNumber* s, int* m) : Obj<QLCDNumber>(s,m) {}
    };
    
    
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    public:
        explicit MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
        void start()
        {
            Slid *sldt = new Slid(sli, &_m);
            connect(sldt, &Slid::finished, sldt, &QObject::deleteLater);
            sldt->start();
    
            Lcd *lcdt = new Lcd(lcd, &_m);
            connect(lcdt, &Lcd::finished, lcdt, &QObject::deleteLater);
            lcdt->start();
        }
    private:
        Ui::MainWindow *ui;
        QSlider* sli;
        QLCDNumber* lcd;
        int _m;
    };
    #endif // MAINWINDOW_H
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow), _m(0)
    {
        ui->setupUi(this);
    
        sli = ui->verticalSlider;
        lcd = ui->lcdNumber;
    
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
        delete sli;
        delete lcd;
    }
    
    
    void Slid::run()
    {
        for(;;) *_m = _s->value();
    }
    
    void Lcd::run()
    {
        for(;;) _s->display(*_m);
    }
    

    main.cpp

    #include "mainwindow.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        MainWindow w;
        w.show();
        w.start();
    
        return a.exec();
    }
    

    The code is compiling pretty well and it works (I can see the lcdnumber changing while I'm modifying the slider). The problem is that this connection stops after few seconds, one of the 2 objects freezes on the screen.

    Is it the good way to run a qt app on 2 threads ? Is there a better way to share memory ?

    Thank you for any advice on this issue,
    Gaetan



  • Hi @GaetanDesrues ,
    Is there a particular reason for using threads ?
    If you need to display value of slider on lcd widget, you can do it with signal-slots with only one line of code.

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow), _m(0)
    {
        ui->setupUi(this);
        //using qOverload requires "CONFIG += c++14" in the pro file, otherwise use "QOverload" alternative with c++11
        connect(ui->verticalSlider, &QSlider::valueChanged, ui->lcdNumber, qOverload<int>(&QLCDNumber::display));
    }
    

    I see several reasons for your app to freeze, first because you access GUI element from thread, which must be avoided, you need to use signal-slots for that.
    Also you are destroying sli and lcd in your MainWindow destructor which will also probably cause a crash when you close the app. You don't need to delete them as they are children of ui and are deleted when delete ui is called.


Log in to reply