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. Use Qt thread correctly
QtWS25 Last Chance

Use Qt thread correctly

Scheduled Pinned Locked Moved Solved General and Desktop
15 Posts 3 Posters 3.1k 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.
  • G Galilio

    How to use qthread with mutex?
    Here is my old code:
    Header:

    class QTcpSocket;
    
    class CAgilentLan : public QThread
    {
    
    public:
    
    	typedef enum 
    	{
    		enRspTimeout = -2, 
    		enRspOffline,
    		enRspOK,
    		enRspError
    	} t_enRspType ;
    
    
    	CAgilentLan(QString strIpAdress_p, int iTimeout_p, bool boSimulate_p=false, bool boDebug_p=false);
    	~CAgilentLan();
    
    	// High-Level Funktionen
    	QByteArray ExecuteGetScreenshot(void);
    	void ExecuteSaveScreenshot(QString &strPathFileName_p, const char *strFormat_p);
    	void ExecuteSettingsSave(unsigned char ucRegisterNo_p);
    	void ExecuteSettingsRecall(unsigned char ucRegisterNo_p);
    	double ExecuteQuickMeasure(unsigned char ucChannel_p, char *pchType_p);
    	double ExecuteStatMeasure(char *pchType_p, bool boTrigger_p);
    	void ExecuteResetMeasurementStatistics(void);
    
    	bool Open(const QString &strIpAdress_p, const int iTimeout_p);
    	bool Close(const int iTimeout_p);
    	t_enRspType Execute(const char *strCmd_p, const int iWaitResponse_p, const int iTimeout_p, const int iRspDelayed_p);
    	QByteArray GetLastResponse(void);
    
    	t_enRspType ExecuteSimulated(const char *strCmd_p);
    	QString GetAgilentIdentifikation();
    
    	...
    
    protected:
    	void run();
    
    private:
    	bool m_boDebug;
    	bool m_boSimulate;
    	
    	QMutex m_MtxProcess;
    	QMutex m_MtxResponse;
    
    	QWaitCondition m_WaitCondProcess;
    	QByteArray m_ByteArrayWrite;
    	QByteArray m_ByteArrayRead;
    
    	QByteArray m_IDN_AgilentIdentification;
    	
    	//Hilfsvariable
    	double m_SDDevPeriodeA ;
    	double m_SDDevDCA;
    	double m_SDDevDCB;
    	double m_SDDevWidthZ;
    
    	double m_OZiSDDevPeriodeA;
    	double m_OZiSDDevDCA;
    	double m_OZiSDDevDCB;
    	double m_OZiSDDevWidthZ;
    
    	double m_OZiMeanPeriodeA;
    	double m_OZiMeanDCA;
    	double m_OZiMeanDCB;
    	double m_OZiMeanWidthZ;
    	
    	QByteArray m_ByteSTDD;
    	QByteArray m_ByteMean;
    	QStringList m_ListSTDDev;
    	QStringList m_ListMean;
    
    	QTcpSocket *m_pTcpSctCtrl;
    	
    	QString m_strCtrlIP;
    	int m_iTimeoutClose;
    	int m_iTimeout;
    	int m_iResponseDelayed;
    	int m_iWaitResponse;
    
    	t_enRspType m_enRetVal;
    };
    
    

    Cpp File:

    CAgilentLan::CAgilentLan(QString strIpAdress_p, int iTimeout_p, bool boSimulate_p, bool boDebug_p):m_SDDevPeriodeA(0), m_SDDevDCA(0),m_SDDevDCB(0),m_SDDevWidthZ(0)
    {
    //	boSimulate_p = false;
    	
    	m_boDebug = boDebug_p;
    	m_boSimulate = boSimulate_p;
    
    	m_enRetVal = enRspOffline;
    	m_strCtrlIP = QString("");
    	m_iTimeout = 0;
    	m_iTimeoutClose = iTimeout_p;
    	if (this->Execute("CreateObject", 0, 0, 0) != enRspOK)
    	{
    		throw(QString("Error AgilentLan.CPP/Constructor TcpSocket Create memory error"));
    	}
    
    	this->Open(strIpAdress_p, iTimeout_p);
    }
    
    CAgilentLan::~CAgilentLan()
    {
    	while(isRunning());
    
    	this->Close(m_iTimeoutClose);
    
    	while(isRunning());
    	
    	if (this->Execute("DeleteObject", 0, 0, 0) != enRspOK)
    	{
    		throw(QString("Error AgilentLan.CPP/Destructor TcpSocket Delete memory error"));
    	}
    
    	
    	while(isRunning());
    }
    bool CAgilentLan::Open(const QString &strCtrlIP_p, const int iTimeout_p)
    {
    	bool boRet_l = true;
    
    	m_strCtrlIP = strCtrlIP_p;
    		
    	if (this->Execute("OpenConnection", 0, iTimeout_p, 0) != enRspOK)
    	{
    		throw(QString("Error AgilentLan.CPP/Open TcpSocket Open Connection error"));
    	}
    	
    	if (m_boDebug)
    	{
    		throw(QString("Tcp Socket is open"));
    	}
    
    	return boRet_l;
    }
    
    bool CAgilentLan::Close(const int iTimeout_p)
    {
    	bool boRet_l = true;
    
    	while(isRunning());
    
    	if (this->Execute("CloseConnection", 0, iTimeout_p, 0) != enRspOK)
    	{
    		throw(QString("Error AgilentLan.CPP/Close Connection error"));
    	}
    	
    	if (m_boDebug)
    	{
    		throw(QString("Tcp Socket is closed"));
    	}
    
    	while(isRunning());
    
    	return boRet_l;
    }
    
    
    CAgilentLan::t_enRspType CAgilentLan::Execute(const char *strCmd_p, const int iWaitResponse_p, const int iTimeout_p, const int iRspDelayed_p)
    {
    	CAgilentLan::t_enRspType enRetVal_l = enRspOffline;
    
    	if (!isRunning())
    	{
    		m_ByteArrayRead.clear();
    
    		m_ByteArrayWrite.clear();
    		m_ByteArrayWrite.append(strCmd_p);
    		
    		m_iWaitResponse = iWaitResponse_p;
    		m_iTimeout = iTimeout_p;
    		m_iResponseDelayed = iRspDelayed_p;
    
    		start();
    
    		m_MtxProcess.lock();
    		m_WaitCondProcess.wait(&m_MtxProcess,-1);
    		m_MtxProcess.unlock();
    	
    		enRetVal_l = this->m_enRetVal;
    	}
    	else
    	{
    		enRetVal_l = enRspError;
    	}
    	
    	while(isRunning());
    	
    	return enRetVal_l;
    }
    
    QByteArray CAgilentLan::GetLastResponse(void)
    {
    	QByteArray ay_l;
    
    	m_MtxResponse.lock();
    	ay_l = m_ByteArrayRead;
    	m_MtxResponse.unlock();
    
    	return ay_l;
    }
    void CAgilentLan::run()
    {
    	bool boRun_l = true;
    	bool boSent_l = false;
    
    	const char *pStrCmd_l = NULL;
    	const char *pStrRsp_l = NULL;
    
    	m_enRetVal = enRspError;
    
    	if (strcmp(m_ByteArrayWrite.data(),"CreateObject")==0)
    	{
    		if (this->m_boSimulate == true)
    		{
    			m_enRetVal = enRspOK;
    		}
    		else
    		{
    			m_pTcpSctCtrl = (QTcpSocket *)new QTcpSocket;
    			if (m_pTcpSctCtrl != NULL)
    			{
    				m_enRetVal = enRspOK;
    			}
    		}
    
    		boRun_l = false;
    	}
    
    	if (strcmp(m_ByteArrayWrite.data(),"DeleteObject")==0)
    	{
    		if (this->m_boSimulate == true)
    		{
    		}
    		else
    		{
    			if (m_pTcpSctCtrl != NULL)
    			{
    				delete m_pTcpSctCtrl;
    			}
    		}
    
    		m_enRetVal = enRspOK;
    		boRun_l = false;
    	}
    
    	if (strcmp(m_ByteArrayWrite.data(),"OpenConnection")==0)
    	{
    		if (this->m_boSimulate == true)
    		{
    			m_enRetVal = enRspOK;
    		}
    		else
    		{
    			m_pTcpSctCtrl->connectToHost(m_strCtrlIP,5025);
    			if (m_pTcpSctCtrl->waitForConnected(m_iTimeout) == true)
    			{
    				m_enRetVal = enRspOK;
    			}
    		}
    		
    		boRun_l = false;
    	}
    
    	if (strcmp(m_ByteArrayWrite.data(),"CloseConnection")==0)
    	{
    		if (this->m_boSimulate == true)
    		{
    			m_enRetVal = enRspOK;
    		}
    		else
    		{
    			m_pTcpSctCtrl->disconnectFromHost();
    			if ((m_pTcpSctCtrl->state() == QAbstractSocket::UnconnectedState) || (m_pTcpSctCtrl->waitForDisconnected(m_iTimeout)))
    			{
    				m_enRetVal = enRspOK;
    			}
    		}
    		
    		boRun_l = false;
    	}
    
    	int iTimeout_l = m_iTimeout;
    	
    	while (boRun_l && (!this->m_boSimulate))
    	{
     		if (boSent_l == false)
    		{
    			boSent_l = true;
    			// Kommando absetzen
    			m_pTcpSctCtrl->write(m_ByteArrayWrite.data(),m_ByteArrayWrite.size());
    			// Auf Antwort warten
    			if (m_iWaitResponse >= 0)
    			{
    				QThread::msleep(m_iWaitResponse);
    			}
    			else
    			{
    				boRun_l = false;
    			}
    		}
    		
    		// Anwort auf Kommando abwarten	
    		if ((m_pTcpSctCtrl->bytesAvailable() > 0) && (boRun_l == true))
    		{
    			m_MtxResponse.lock();
    
    			m_ByteArrayRead.append(m_pTcpSctCtrl->readAll());
    			
    			if (m_boDebug)
    			{
    				throw(QString(m_ByteArrayRead.data()));
    			}
    
    			m_MtxResponse.unlock();
    
    			iTimeout_l = m_iTimeout;
    //			iTimeout_l = m_iWaitResponse;
    		}
    		else
    		{
    			if (m_pTcpSctCtrl->waitForReadyRead(iTimeout_l) == false)
    			{
    				m_MtxResponse.lock();
    
    				if (m_ByteArrayRead.size() == 0)
    				{
    					if (m_boDebug)
    					{
    						throw(QString("AgilentLan Timeout"));
    					}
    					m_enRetVal = enRspTimeout;
    				}
    				else
    				{
    					m_enRetVal = enRspOK;
    				}
    
    				m_MtxResponse.unlock();
    				
    				boRun_l = false;					
    			}
    		}
    	}
    	
    	QThread::msleep(m_iResponseDelayed);
    	
    	QMutexLocker locker(&m_MtxProcess);
    
    	m_WaitCondProcess.wakeOne();
    
    }
    

    This code section I have adapted to the following:

    class CAgilentLan : public QObject
    {
    	Q_OBJECT
     
    public:
     ...
        CAgilentLan(QString strIpAdress_p, int iTimeout_p, bool boSimulate_p=false, bool boDebug_p=false);
        ~CAgilentLan();
     
    ...
        t_enRspType Execute(const char *strCmd_p, const int iWaitResponse_p, const int iTimeout_p, const int iRspDelayed_p);
     ..
     
    public slots:
       void init();
       void openCommunikation();
        void AgilentStart();
    signals:
    void finished();
    ....
     
    
    };
    

    what is wrong?

    jsulmJ Offline
    jsulmJ Offline
    jsulm
    Lifetime Qt Champion
    wrote on last edited by
    #3

    @Galilio This can be simplified:

    QByteArray CAgilentLan::GetLastResponse(void)
    {
    	QByteArray ay_l;
    
    	m_MtxResponse.lock();
    	ay_l = m_ByteArrayRead;
    	m_MtxResponse.unlock();
    
    	return ay_l;
    }
    

    to

    QByteArray CAgilentLan::GetLastResponse(void)
    {
    	QMutexLocker(m_MtxResponse);
    	return m_ByteArrayRead;
    }
    

    https://forum.qt.io/topic/113070/qt-code-of-conduct

    C 1 Reply Last reply
    2
    • G Offline
      G Offline
      Galilio
      wrote on last edited by
      #4

      At a class where I have the object "CAgilentLan"
      Calls I write in the contructor the following:

      //CAgilentLan* m_pvAgilentWorker; 
      m_pvWorkerThread = new QThread();
      m_pvAgilentWorker = new CAgilentLan(settings_l.strfuGetIP_DSO(), 500, settings_l.bofuGetSimulate());
      m_pvAgilentWorker->moveToThread(m_pvWorkerThread);
      connect(m_pvWorkerThread, &QThread::started, m_pvAgilentWorker, &CAgilentLan::agilentStart);
         
      connect(m_pvWorkerThread, &QThread::finished, m_pvWorkerThread, &QThread::deleteLater);
      connect(m_pvWorkerThread, &QThread::finished, m_pvWorkerThread, &CAgilentLan::deleteLater);
      m_pvWorkerThread->start();
      

      This is the error message:

      ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 4c19f68. Receiver '' (of type 'QNativeSocketEngine') was created in thread 4c582e0", file kernel\qcoreapplication.cpp, line 541
      
      1 Reply Last reply
      0
      • jsulmJ jsulm

        @Galilio This can be simplified:

        QByteArray CAgilentLan::GetLastResponse(void)
        {
        	QByteArray ay_l;
        
        	m_MtxResponse.lock();
        	ay_l = m_ByteArrayRead;
        	m_MtxResponse.unlock();
        
        	return ay_l;
        }
        

        to

        QByteArray CAgilentLan::GetLastResponse(void)
        {
        	QMutexLocker(m_MtxResponse);
        	return m_ByteArrayRead;
        }
        
        C Offline
        C Offline
        corruptedsyntax
        wrote on last edited by
        #5

        @jsulm

        QByteArray CAgilentLan::GetLastResponse(void)
        {
            QMutexLocker(m_MtxResponse);
            return m_ByteArrayRead;
        }
        

        Won't that temporary QMutexLocker need a name? Otherwise it will be deconstructed as a temporary object at the end of the first statement and the return won't be locked properly.

        jsulmJ 1 Reply Last reply
        1
        • C corruptedsyntax

          @jsulm

          QByteArray CAgilentLan::GetLastResponse(void)
          {
              QMutexLocker(m_MtxResponse);
              return m_ByteArrayRead;
          }
          

          Won't that temporary QMutexLocker need a name? Otherwise it will be deconstructed as a temporary object at the end of the first statement and the return won't be locked properly.

          jsulmJ Offline
          jsulmJ Offline
          jsulm
          Lifetime Qt Champion
          wrote on last edited by
          #6

          @corruptedsyntax Sure, thanks for pointing that out :-)

          QByteArray CAgilentLan::GetLastResponse(void)
          {
              QMutexLocker mutexLocker(m_MtxResponse);
              return m_ByteArrayRead;
          }
          

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          G 1 Reply Last reply
          0
          • jsulmJ jsulm

            @corruptedsyntax Sure, thanks for pointing that out :-)

            QByteArray CAgilentLan::GetLastResponse(void)
            {
                QMutexLocker mutexLocker(m_MtxResponse);
                return m_ByteArrayRead;
            }
            
            G Offline
            G Offline
            Galilio
            wrote on last edited by
            #7

            @jsulm
            Hi,
            So is correct:

            QByteArray CAgilentLan::GetLastResponse(void)
            {
                QMutexLocker mutexLocker(&m_MtxResponse);
                return m_ByteArrayRead;
            }
            
            jsulmJ 1 Reply Last reply
            0
            • G Galilio

              @jsulm
              Hi,
              So is correct:

              QByteArray CAgilentLan::GetLastResponse(void)
              {
                  QMutexLocker mutexLocker(&m_MtxResponse);
                  return m_ByteArrayRead;
              }
              
              jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote on last edited by
              #8

              @Galilio yes

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              G 1 Reply Last reply
              0
              • G Offline
                G Offline
                Galilio
                wrote on last edited by
                #9

                Hi,
                How can I avoid this error?

                1 Reply Last reply
                0
                • jsulmJ jsulm

                  @Galilio yes

                  G Offline
                  G Offline
                  Galilio
                  wrote on last edited by
                  #10

                  @jsulm
                  Problem occurs when the application is exited.
                  The Destructor is then called, which looks like this:

                  CAgilentLan::~CAgilentLan()
                  {
                  	this->Close(GetiTimeOutClose());
                  
                  	if (this->Execute("DeleteObject", 0, 0, 0) != enRspOK)
                  	{
                  		throw(QString("Error AgilentLan.CPP/Destructor TcpSocket Delete memory error"));
                  	}
                  }
                  

                  And right here is the problem:

                  GetTcpSocket()->disconnectFromHost();
                  
                  jsulmJ 1 Reply Last reply
                  0
                  • G Galilio

                    @jsulm
                    Problem occurs when the application is exited.
                    The Destructor is then called, which looks like this:

                    CAgilentLan::~CAgilentLan()
                    {
                    	this->Close(GetiTimeOutClose());
                    
                    	if (this->Execute("DeleteObject", 0, 0, 0) != enRspOK)
                    	{
                    		throw(QString("Error AgilentLan.CPP/Destructor TcpSocket Delete memory error"));
                    	}
                    }
                    

                    And right here is the problem:

                    GetTcpSocket()->disconnectFromHost();
                    
                    jsulmJ Offline
                    jsulmJ Offline
                    jsulm
                    Lifetime Qt Champion
                    wrote on last edited by
                    #11

                    @Galilio What error? What problem? Can you be more precise?
                    You should not throw exceptions from destructors.

                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                    G 1 Reply Last reply
                    0
                    • jsulmJ jsulm

                      @Galilio What error? What problem? Can you be more precise?
                      You should not throw exceptions from destructors.

                      G Offline
                      G Offline
                      Galilio
                      wrote on last edited by Galilio
                      #12

                      @jsulm
                      The TcpSocket connection can not be closed
                      Error is:

                      ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread dc02d0. Receiver '' (of type 'QNativeSocketEngine') was created in thread 4912418", file kernel\qcoreapplication.cpp, line 541
                      
                      
                      jsulmJ 1 Reply Last reply
                      0
                      • G Galilio

                        @jsulm
                        The TcpSocket connection can not be closed
                        Error is:

                        ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread dc02d0. Receiver '' (of type 'QNativeSocketEngine') was created in thread 4912418", file kernel\qcoreapplication.cpp, line 541
                        
                        
                        jsulmJ Offline
                        jsulmJ Offline
                        jsulm
                        Lifetime Qt Champion
                        wrote on last edited by
                        #13

                        @Galilio You are doing something wrong with your threads

                        https://forum.qt.io/topic/113070/qt-code-of-conduct

                        G 1 Reply Last reply
                        0
                        • jsulmJ jsulm

                          @Galilio You are doing something wrong with your threads

                          G Offline
                          G Offline
                          Galilio
                          wrote on last edited by
                          #14

                          @jsulm
                          Yes but what?
                          My QThread looks like this:

                          m_pvWorkerThread = new QThread();
                          m_pvAgilentWorker = new CAgilentLan(settings_l.strfuGetIP_DSO(), 500, settings_l.bofuGetSimulate());
                          m_pvAgilentWorker->moveToThread(m_pvWorkerThread);
                          connect(m_pvWorkerThread, &QThread::started, m_pvAgilentWorker, &CAgilentLan::agilentStart);
                             
                          connect(m_pvWorkerThread, &QThread::finished, m_pvWorkerThread, &QThread::deleteLater);
                          connect(m_pvWorkerThread, &QThread::finished, m_pvWorkerThread, &CAgilentLan::deleteLater);
                          m_pvWorkerThread->start();
                          
                          jsulmJ 1 Reply Last reply
                          0
                          • G Galilio

                            @jsulm
                            Yes but what?
                            My QThread looks like this:

                            m_pvWorkerThread = new QThread();
                            m_pvAgilentWorker = new CAgilentLan(settings_l.strfuGetIP_DSO(), 500, settings_l.bofuGetSimulate());
                            m_pvAgilentWorker->moveToThread(m_pvWorkerThread);
                            connect(m_pvWorkerThread, &QThread::started, m_pvAgilentWorker, &CAgilentLan::agilentStart);
                               
                            connect(m_pvWorkerThread, &QThread::finished, m_pvWorkerThread, &QThread::deleteLater);
                            connect(m_pvWorkerThread, &QThread::finished, m_pvWorkerThread, &CAgilentLan::deleteLater);
                            m_pvWorkerThread->start();
                            
                            jsulmJ Offline
                            jsulmJ Offline
                            jsulm
                            Lifetime Qt Champion
                            wrote on last edited by jsulm
                            #15

                            @Galilio Sorry, currently I have no time to analyse your code.
                            You should read: https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

                            https://forum.qt.io/topic/113070/qt-code-of-conduct

                            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