Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Slot priority in multithread

Slot priority in multithread

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 2 Posters 1.8k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    maratk1n
    wrote on last edited by maratk1n
    #1

    Hi all!

    Small fragment of the project:

    mainwindow.cpp

    //constructor
        QThread *thread = new QThread;         
        //thread = new QThread(this);             
        valve = new Valve(7);                   
        pressureSensors = new PressureSensors;  
        valve->moveToThread(thread);
        pressureSensors->moveToThread(thread);
        connect(pressureSensors, SIGNAL(remoteSignal(bool)), this, SLOT(readPressureSensors(bool)));
        connect(valve, SIGNAL(remoteSignal(bool)), this, SLOT(updateStates(bool)));
        connect(this, SIGNAL(valveOpen(int)), valve, SLOT(open(int)));
        connect(this, SIGNAL(valveClose(int)), valve, SLOT(close(int)));
        connect(valve, SIGNAL(valveStatus(int,bool,bool)), this, SLOT(valveIndicate(int,bool,bool)));
        QTimer *sensorsReadTimer = new QTimer(this);    
        sensorsReadTimer->moveToThread(thread);
        connect(sensorsReadTimer, SIGNAL(timeout()), pressureSensors, SLOT(readSensors()));
        sensorsReadTimer->start(100);                   
        QTimer *valvesReadTimer = new QTimer(this);     
        valvesReadTimer->moveToThread(thread);
        connect(valvesReadTimer, SIGNAL(timeout()), valve, SLOT(getAllStates()));
        valvesReadTimer->start(100);                   
        thread->start();
    //***//
    void MainWindow::openValve(int id)
    {
        valveButton[id]->setEnabled(false);
        //valve->open(id);
        emit valveOpen(id);
    }
    

    protocol.cpp

    bool Valve::open(int id)
    {
        QByteArray arr;
        arr.resize(7);
        arr[0] = 0xAB;
        arr[1] = 0x01;
        arr[2] = 0x02;
        arr[3] = 0x02;
        arr[4] = id + 1;
        arr[5] = 0xFF;
        arr[6] = 0x00 - arr[1] - arr[2] - arr[3] - arr[4] - arr[5];
    
        QByteArray response = ComPort::get().requestResponse(arr);
        if(response[0] == arr[0])
        {
            qDebug() << "клапан №: " << id << " открыт!";
            valveState[id] = true;
            emit valveStatus(id, 1, 1);
            return 1;
        }
        emit valveStatus(id, 1, 0);
        return 0;
    }
    bool Valve::getAllStates()
    {
        QByteArray arr;
        arr.resize(5);
        arr[0] = 0xAB;
        arr[1] = 0x01;
        arr[2] = 0x00;
        arr[3] = 0x00;
        arr[4] = 0x00 - arr[1] - arr[2] - arr[3];
    
        QByteArray response = ComPort::get().requestResponse(arr);
        if(response[0] == arr[0])
        {
            QBitArray bitStates(16);   
    
            for (int i = 4; i<6; i++)   
                for (int b = 0; b<8; b++)
                    bitStates.setBit((i-4)*8+b, response.at(i)&(1<<b));
            for (int i = 0; i < valveState.size(); i++)         
                valveState[i] = bitStates[i];
            for (uint i = 0; i < sizeof(fittingState); i++) 
                fittingState[i] = bitStates[i+8];
            emit remoteSignal(1);
            return 1;
        }
        emit remoteSignal(0);
        return 0;
    }
    //***//
    QByteArray ComPort::requestResponse(const QByteArray &data)
    {
        mutex->lock();
        QByteArray readBuf;
        qDebug() << "-------------------------";
        if(!serial->isOpen())
            open();
        int attempts = 1;
        while (attempts <= REQATTEMPTS) {      //3 попытки
            if (serial->isWritable())
            {
                serial->write(data);
                qDebug() << "Попытка № " << attempts;
                qDebug() << "Запрос: " << data.toHex();
                while (serial->waitForReadyRead(WAITFORREADY)) {
                    readBuf += serial->readAll();
                    if (crcCheck(readBuf) && data[2] == readBuf[2] ){  //если CRC и команда сошлись -- успех!
                        qDebug() << "Ответ: " << readBuf.toHex();
    
                        responseCount++;
                        qDebug() << "Кол-во запросов:  " << responseCount;
                        qDebug() << "Кол-во таймаутов: " << timeoutCount;
                        float percent = timeoutCount * 100;
                        percent = percent / responseCount;
                        qDebug() << "Процент косяков:  " << QString::number(percent, 'f', 3) << "%";
    
                        close();
                        mutex->unlock();
                        return readBuf;
                    }
                }
                //qDebug() << readBuf.toHex();
                readBuf.clear();
                qDebug() << "Таймаут...";
    
                timeoutCount++;
    
                close();
                open();
                attempts++;
            }
            else
            {
                qDebug() << "Порт " << portName << " не пишется!";
                close();
                mutex->unlock();
                return 0;
            }
    
        }
        close();
        mutex->unlock();
        return 0;
    }
    

    If I do not put valve and pressureSensors in a separate thread, then everything works more or less normally.
    But if I put them in a separate thread, the valve opening slot works very late (~ 10-20 seconds, as lucky). As I understand it, this is because the signal is emitted from the main thread, and the slot is in the other thread. Is it possible to build a queue?

    Slot open from Valve class must have the highest priority

    Thankful in advance for the help!

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #2

      Since you've given a parent to the timers they wouldn't be able to move them to another thread.

      My suspect is that it's not a problem of the connection itself but of your blocking design of the serial read. Try connecting a slot or lambda to readyRead instead of using waitForReadyRead

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      M 1 Reply Last reply
      2
      • VRoninV VRonin

        Since you've given a parent to the timers they wouldn't be able to move them to another thread.

        My suspect is that it's not a problem of the connection itself but of your blocking design of the serial read. Try connecting a slot or lambda to readyRead instead of using waitForReadyRead

        M Offline
        M Offline
        maratk1n
        wrote on last edited by
        #3

        @VRonin
        Timers have nothing to do with it. I tried it differently. The poll of the valves unambiguously moves to a separate thread, as the graphical interface stops lagging.
        I need to wait a certain amount of time to get a response on the port, otherwise continue the poll. The valve opening slot for some reason starts very late (check with qDebug())

        VRoninV 1 Reply Last reply
        0
        • M maratk1n

          @VRonin
          Timers have nothing to do with it. I tried it differently. The poll of the valves unambiguously moves to a separate thread, as the graphical interface stops lagging.
          I need to wait a certain amount of time to get a response on the port, otherwise continue the poll. The valve opening slot for some reason starts very late (check with qDebug())

          VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #4

          @maratk1n said in Slot priority in multithread:

          I need to wait

          Yes, my point is that you do not, you can use it asynchronously

          @maratk1n said in Slot priority in multithread:

          The valve opening slot for some reason starts very late

          This is probably because the event loop in the receiver is busy

          @maratk1n said in Slot priority in multithread:

          Timers have nothing to do with it.

          Agree, nevertheless they are not moved to the separate thread

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          1 Reply Last reply
          1
          • M Offline
            M Offline
            maratk1n
            wrote on last edited by
            #5

            Changed some code. This, it seems, helped to solve the problem.

            ...
                QTimer *sensorsReadTimer = new QTimer(this);    // <<<<<<<<<< Change to new QTimer();
                sensorsReadTimer->moveToThread(thread);
                connect(sensorsReadTimer, SIGNAL(timeout()), pressureSensors, SLOT(readSensors()));
                sensorsReadTimer->start(100);    // <<<<<<<<<< Start the timer before moving to the thread                   
                QTimer *valvesReadTimer = new QTimer(this);     // <<<<<<<<<< Change to new QTimer();    
                valvesReadTimer->moveToThread(thread);
                connect(valvesReadTimer, SIGNAL(timeout()), valve, SLOT(getAllStates()));
                valvesReadTimer->start(100);    // <<<<<<<<<< Start the timer before moving to the thread                   
                ...
            

            @VRonin Thanks :)

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved