To Pass object into Thread



  • Hi!

    I have a MainWindow class that has 4 objects of ChannelOptions class. (They're input signal channels, each iof them has properties like signal type etc...).
    When the application is running, sometimes they may be changed:

    void MainWindow::OpenOptionsWindow()
    {
        Options *optionsobj = new Options;
        optionsobj->exec();
      
        channel1object.ReadSingleChannelOptionFromFile(1);
        channel2object.ReadSingleChannelOptionFromFile(2);
        channel3object.ReadSingleChannelOptionFromFile(3);
        channel4object.ReadSingleChannelOptionFromFile(4);
    
    void ChannelOptions::ReadSingleChannelOptionFromFile(int channel)
    {
        QFile infile(pathtofile + "options.txt");
        infile.open(QIODevice::ReadOnly);
        QTextStream in(&infile);
        QString sss = in.readLine();
        QJsonDocument doc = QJsonDocument::fromJson(sss.toUtf8());
        QJsonObject json = doc.object();
        QJsonArray array = json["channels"].toArray();
        QJsonObject ch = array.at(channel-1).toObject();
    
        this->SetHigherLimit(ch.value("HigherLimit").toDouble());
        this->SetLowerLimit(ch.value("LowerLimit").toDouble());
        this->SetHigherMeasureLimit(ch.value("HigherMeasLimit").toDouble());
        this->SetLowerMeasureLimit(ch.value("LowerMeasLimit").toDouble());
        this->SetSignalType(ch.value("Type").toDouble());
        this->SetUnitsName(ch.value("Units").toString());
        this->SetMeasurePeriod(ch.value("Period").toDouble());
        this->SetState1HighMessage(ch.value("State1HighMessage").toString());
        this->SetState1LowMessage(ch.value("State1LowMessage").toString());
        this->SetState2HighMessage(ch.value("State2HighMessage").toString());
        this->SetState2LowMessage(ch.value("State2LowMessage").toString());
        this->SetState1Value(ch.value("State1Value").toDouble());
        this->SetState2Value(ch.value("State2Value").toDouble());
        this->SetChannelName(ch.value("Name").toString());
        this->SetMathematical(ch.value("MathWork").toBool());
        this->SetMathEquation(ch.value("MathString").toString());
    
        infile.close();
    }
    

    And i have a thread that reads data from that signal channels.

    void ModBus::ReadAllChannelsThread ()
    {
        UartDriver UD;
        double currentdata;
        this->thread()->setPriority(QThread::LowPriority);
    
        while (1)
        {
            while (
                   (UartDriver::needtoupdatechannel[0] == 0)&&
                   (UartDriver::needtoupdatechannel[1] == 0)&&
                   (UartDriver::needtoupdatechannel[2] == 0)&&
                   (UartDriver::needtoupdatechannel[3] == 0))
            {
                this->thread()->msleep(20);
            }
    
            if (UartDriver::needtoupdatechannel[0] == 1)
            {
                UartDriver::needtoupdatechannel[0] = 0;
                //  currentdata = ClickRelay(ModBus::Board4AIAddress);
    
                currentdata = ReadDataChannel(ModBus::ElmetroChannelAB1Address);
    
                if (currentdata!=0)
                {
                    UD.writechannelvalue(1,currentdata);
                }
                this->thread()->msleep(25);
            }
    
            currentdata=0;
    
            if (UartDriver::needtoupdatechannel[1] == 1)
            {
                UartDriver::needtoupdatechannel[1] = 0;
                currentdata = ReadDataChannel(ModBus::ElmetroChannelAB2Address);
                if (currentdata!=0)
                {
                    UD.writechannelvalue(2,currentdata);
                }
                this->thread()->msleep(25);
            }
    
            currentdata=0;
    
            if (UartDriver::needtoupdatechannel[2] == 1)
            {
                UartDriver::needtoupdatechannel[2] = 0;
                currentdata = ReadDataChannel(ModBus::ElmetroChannelAB3Address);
                if (currentdata!=0)
                {
                    UD.writechannelvalue(3,currentdata);
                }
                this->thread()->msleep(25);
            }
            currentdata=0;
    
            if (UartDriver::needtoupdatechannel[3] == 1)
            {
                UartDriver::needtoupdatechannel[3] = 0;
                currentdata = ReadDataChannel(ModBus::ElmetroChannelAB4Address);
                if (currentdata!=0)
                {
                    UD.writechannelvalue(4,currentdata);
                }
                this->thread()->msleep(25);
            }
            currentdata=0;
        }
    }
    

    Now i want to read data in that Thread that depends of signal type.

    For example if channel's signal type is Volts i want to:

     currentdata = ReadVoltage(ModBus::ElmetroChannelAB1Address);
    

    ... if it's Termocouple i want to:

     currentdata = ReadThermocouple(ModBus::ElmetroChannelAB1Address);
    

    the question is how this thread should to know signal type of each of 4 objects that are defined in MainWindow.

    And please any review of my hard code is pleased. Thanks



  • tried to start thread with 4 objects, but i bet it's not a good idea

        thread2= new QThread();
        ModBus *MB;
        MB = new ModBus();
        MB->moveToThread(thread2);
        //connect(thread2, SIGNAL(started()), MB, SLOT(ReadAllChannelsThread()) );
        thread2->start();
        connect( this, SIGNAL(ThreadSignal( ChannelOptions*, ChannelOptions*,ChannelOptions*, ChannelOptions* )), MB, SLOT(ThreadReact(ChannelOptions*,ChannelOptions*,ChannelOptions*,ChannelOptions*)) ); //
        connect(MB, SIGNAL(finished()), MB, SLOT(deleteLater()));
        ThreadSignal(&channel1object,&channel2object,&channel3object,&channel4object);
    


  • So this is dangerous. You are passing memory around between threads without any sort of thread synchronization.

    Your objects are not mutexed. If you happen to write in both threads at once you will crash. If you read while writing in a thread you will crash.

    Do the ChannelOption objects really need to be created in the main thread? It's fine if they do but if you pass them to other threads you will need to protect them with QMutex or some other synchronization object.

    As for passing 4 objects, there's nothing wrong with that. If you wanted to combine them into one you could just do a QList<ChannelObject *> or something. Then you are just passing one. You could also make a class or struct. I would do the class route to handle mutexing for you as well.



  • @ambershark

    Cool, thank you, very useful!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.