can we use the Qtimer & QeventLoop in different thread?



  • void RecoveryProcessLoader::dataReceiveingSwitch(bool dataRxSwitch) {

    if (dataRxSwitch && (!previousSignalVal)) {
    	
    	previousSignalVal = true;
    	
    	emit Started();
    	emit ProgressChanged(0);
    	this->moveToThread(&progressBarThread);
    	progressBarThread.start();
    	
    }
    else if ((!dataRxSwitch) &&(previousSignalVal)){
    	previousSignalVal = false;
    	
    	progressBarThread.exit(EXIT_CORRECTLY);
    	if (!progressBarThread.isFinished()) {
    		progressBarThread.wait();
    	}
    	
    	emit Finished(true);
    }
    

    }

    void RecoveryProcessLoader::setProgressbarValue() {
    QEventLoop loop;
    QTimer timer;

    //timer.setInterval(1000);
    
    QEventLoop *loopPtr = &loop;
    

    #define EXIT_BY_TIMER 1
    #define EXIT_BY_PING 0

    QList<QMetaObject::Connection> connections;
    
    connections << connect(this, &RecoveryProcessLoader::dataReceivePing, [=]() {
    	emit ProgressChanged((numberOfReceiveByte * 100) / totalNumberOfbyte);
    	loopPtr->exit(EXIT_BY_PING);
    });
    
    connections << connect(&timer, &QTimer::timeout, [=]() {
    	loopPtr->exit(EXIT_BY_TIMER);
    });
    
    timer.start(1000);
    int ret = loopPtr->exec();
    timer.stop();
    
    foreach(auto conn, connections) {
    	disconnect(conn);
    }
    
    if (ret != EXIT_BY_PING) {
    	progressBarThread.quit();
    
    	if (!progressBarThread.isFinished()) {
    		progressBarThread.wait();
    	}
    
    	emit Finished(false);
    	return;
    }
    

    }

    setProgressbarValue is start to execute on started siganl of progressBarThread thread. here int ret = loopPtr->exec(); return -1. what is wrong with timeout signal of timer. I am not getting time out signal and dataReceivePing signal.


  • Moderators

    Please put your code between code tags. It is very hard to read in it's current form.

    this->moveToThread(&progressBarThread);
    progressBarThread.start(); 
    

    Moving current object to another thread is not a good idea. Especially when your thread is a child/ local variable of that same object.

    Where is progressBarThread defined?

    void RecoveryProcessLoader::setProgressbarValue() {
    

    Is this method run in your new thread or your main thread?



  • @sierdzio

    //********* RecoveryLoader.h ************//

    #pragma once
    
    #include <global_typedefs.h>
    #include <QThread>
    #include <qtimer.h>
    #include <qeventloop.h>
    
    
    #define EXIT_CORRECTLY 0
    #define EXIT_INCORRECTLY 1
    
    class RecoveryProcessLoader : public QObject
    {
    	Q_OBJECT
    public:
    	static RecoveryProcessLoader* Instance();
    
    public:
    	 void RecordReceiveByte(const uint NumberOfReceiveByte);
    	 void calculateTotalBytes(const HardwareModel_t HWversion, const uint32_t numPagesUsed);
    	 
    signals :
    	void ProgressChanged(int);
    	void Finished(bool);
    	void Started();
    	void dataReceivePing();
    	
    
    public slots:
    	void dataReceiveingSwitch(bool);
    	void setProgressbarValue();
    private:
    	RecoveryProcessLoader();
    	~RecoveryProcessLoader();
    	uint getPageSize(const HardwareModel_t);
    	volatile uint numberOfReceiveByte;
    	volatile uint totalNumberOfbyte;
    	QThread progressBarThread;
    
    	bool previousSignalVal = false;
    };
    
    

    //***********************RecoveryLoader.cpp ********************//

    #include "RecoveryLoader.h"
    
    
    RecoveryProcessLoader* RecoveryProcessLoader::Instance() {
    	static RecoveryProcessLoader * ret = 0 ;
    	if (0 == ret) {
    		ret = new RecoveryProcessLoader;
    	}
    	return ret;
    }
    
    RecoveryProcessLoader::RecoveryProcessLoader(){
    	QObject::connect(&progressBarThread, &QThread::started, this, &RecoveryProcessLoader::setProgressbarValue,Qt::DirectConnection);
    	
    }
    
    RecoveryProcessLoader::~RecoveryProcessLoader() {
    	QObject::disconnect(&progressBarThread, &QThread::started, this, &RecoveryProcessLoader::setProgressbarValue);
    }
    
    uint RecoveryProcessLoader:: getPageSize(const HardwareModel_t HWversion) {
    
    	auto pageSizeOfFlash = 512;
    	
    	return pageSizeOfFlash;
    }
    
    
    void RecoveryProcessLoader::calculateTotalBytes(const HardwareModel_t HWversion,const uint32_t numPagesUsed) {
    	numberOfReceiveByte = 0;
    	auto pageSize = getPageSize(HWversion);
    	totalNumberOfbyte = pageSize * 1;
    	return;
    	totalNumberOfbyte = pageSize * numPagesUsed;
    }
    
    void RecoveryProcessLoader::RecordReceiveByte(const uint numberOfByte) {
    	numberOfReceiveByte += numberOfByte;
    }
    
    
    
    void RecoveryProcessLoader::dataReceiveingSwitch(bool dataRxSwitch) {
    	
    	if (dataRxSwitch && (!previousSignalVal)) {
    		
    		previousSignalVal = true;
    		
    		emit Started();
    		emit ProgressChanged(0);
    		this->moveToThread(&progressBarThread);
    		progressBarThread.start();
    		
    	}
    	else if ((!dataRxSwitch) &&(previousSignalVal)){
    		previousSignalVal = false;
    		
    		progressBarThread.exit(EXIT_CORRECTLY);
    		if (!progressBarThread.isFinished()) {
    			progressBarThread.wait();
    		}
    		
    		emit Finished(true);
    	}
    }
    
    
    void RecoveryProcessLoader::setProgressbarValue() {
    	QEventLoop loop;
    	QTimer timer;
    
    	//timer.setInterval(1000);
    
    	QEventLoop *loopPtr = &loop;
    
    #define EXIT_BY_TIMER	1
    #define EXIT_BY_PING	0
    
    	QList<QMetaObject::Connection> connections;
    
    	QObject::connect(this, &RecoveryProcessLoader::dataReceivePing, [=]() {
    		emit ProgressChanged((numberOfReceiveByte * 100) / totalNumberOfbyte);
    		loopPtr->exit(EXIT_BY_PING);
    	});
    	
    	QObject::connect(&timer, &QTimer::timeout, [=]() {
    		loopPtr->exit(EXIT_BY_TIMER);
    	});
    
    	timer.start(1000);
    	int ret = loopPtr->exec();
    	timer.stop();
    
    	foreach(auto conn, connections) {
    		disconnect(conn);
    	}
    
    	if (ret != EXIT_BY_PING) {
    		progressBarThread.quit();
    
    		if (!progressBarThread.isFinished()) {
    			progressBarThread.wait();
    		}
    
    		emit Finished(false);
    		return;
    	}
    }
    

    Thank you @sierdzio for you advise. Here i put my full code. I am writing this code for updating the Progress Bar Value.



  • @sierdzio I am Trying to create the separate thread which is continuously update the progrss bar on arrival of the data.



  • @SGaist what change do i need to make sir?? could you please guid me??



  • This Code Work fine but i don't know the different. any one please give advise, what was the mistake, I was doing wrong if class derive from QObject.

    if I will move the object into working thread then also it is working good.
    but I don't know, why it was not working if I derive the class from the Object and use the Qthread Object.

    what is different in between two things?

    Just for note: my dataReceiveingSwitch signal is working into main thread in both case.

    /********************RecoveryLoader.h ********************/

    #pragma once
    
    #include <global_typedefs.h>
    #include <QThread>
    #include <qtimer.h>
    #include <qeventloop.h>
    #include "qapplication.h"
    
    #define EXIT_CORRECTLY 0
    #define EXIT_INCORRECTLY 1
    
    class RecoveryProcessLoader : public QThread
    {
    	Q_OBJECT
    public:
    	static RecoveryProcessLoader* Instance();
    
    public:
    	 void RecordReceiveByte(const uint NumberOfReceiveByte);
    	 void calculateTotalBytes(const HardwareModel_t HWversion, const uint32_t numPagesUsed);
    	 
    signals :
    	void ProgressChanged(int);
    	void Finished(bool);
    	void Started();
    	void dataReceivePing();
    	
    public slots:
    	void dataReceiveingSwitch(bool);
    
    private:
    	RecoveryProcessLoader();
    	uint getPageSize(const HardwareModel_t);
    	volatile uint numberOfReceiveByte;
    	volatile uint totalNumberOfbyte;
    	bool previousSignalVal = false;
    	void run();
    };
    
    

    /****RecoveryLoader.cpp/

    #include "RecoveryLoader.h"
    
    
    RecoveryProcessLoader* RecoveryProcessLoader::Instance() {
    	static RecoveryProcessLoader * ret = 0 ;
    	if (0 == ret) {
    		ret = new RecoveryProcessLoader;
    	}
    	return ret;
    }
    
    RecoveryProcessLoader::RecoveryProcessLoader(){
    	//this->moveToThread(this);
    }
    
    uint RecoveryProcessLoader::getPageSize(const HardwareModel_t HWversion) {
    
    
    	return pageSizeOfFlash;
    }
    
    
    void RecoveryProcessLoader::calculateTotalBytes(const HardwareModel_t HWversion,const uint32_t numPagesUsed) {
    	numberOfReceiveByte = 0;
    	auto pageSize = getPageSize(HWversion);
    	totalNumberOfbyte = pageSize * 1;
    	return;
    	totalNumberOfbyte = pageSize * numPagesUsed;
    }
    
    void RecoveryProcessLoader::RecordReceiveByte(const uint numberOfByte) {
    	numberOfReceiveByte += numberOfByte;
    }
    
    void RecoveryProcessLoader::dataReceiveingSwitch(bool dataRxSwitch) {
    	
    	if (dataRxSwitch && (!previousSignalVal)) {
    		
    		previousSignalVal = true;
    
    		emit ProgressChanged(0);
    		emit Started();
    		this->start();
    	}
    	else if ((!dataRxSwitch) &&(previousSignalVal)){
    		previousSignalVal = false;
    		
    		this->exit(EXIT_CORRECTLY);
    		if (!this->isFinished()) {
    			this->wait();
    		}
    
    		emit ProgressChanged(100);
    		emit Finished(true);
    		
    	}
    	else {
    		NULL;
    	}
    }
    
    // This Thread may through wrong value for Finished signal if the dataReceiveingSwitch signal does not received in correct order.
    #define EXIT_BY_TIMER	1
    #define EXIT_BY_PING	0
    
    void RecoveryProcessLoader::run() {
    	QTimer timer;
    	QEventLoop loop;
    	QEventLoop *loopPtr = &loop;
    	QList<QMetaObject::Connection> connections;
    
    	connections << connect(this, &RecoveryProcessLoader::dataReceivePing, [=](){
    		emit ProgressChanged((numberOfReceiveByte * 100) / totalNumberOfbyte);
    		loopPtr->exit(EXIT_BY_PING);
    		});
    
    	connections << connect(&timer, &QTimer::timeout, [=]() {
    		loopPtr->exit(EXIT_BY_TIMER);
    	});
    
    	timer.start(10);
    	int ret = loopPtr->exec();
    	timer.stop();
    
    	foreach(auto conn, connections) {
    		disconnect(conn);
    	}
    
    	if (ret != EXIT_BY_PING) {
    		this->exit(EXIT_INCORRECTLY);
    
    		if (!this->isFinished()) {
    			this->wait();
    		}
    		emit Finished(false);
    		return;
    	}
    }
    


  • Hi @Yahoo!

    Please read Maya's blog on threading in Qt5: https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ for the best explanation on threading for Qt that is not in the docs.

    Using the worker thread based off QObject will allow your timer to work from the thread without having to touch the event queue. I have found I NEVER want to override run anymore. My worker object sets up the timer in the start slot and emits a signal to the client while running. This will tru;y make you app event driven and waiting or "processing" the event queue is rendered unnecessary.

    I have several posts about this and it really is a nice way to work with the objects. For functional style threads, I use QFuture.



  • @Buckwheat Thank you documents link. I will read it and trying to make change in my code. thank you @Buckwheat .


Log in to reply
 

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