Hello,
Im developing a console application in which the main thread is continuously reading and parsing user input commands. One of that commands is called "loop" and with that I want to start loop after the user press ENTER and stops it when the user press ENTER again.
So I have something like this:
(MainThread)
loop->start();
loop->stop();
while(getchar() != '\n') QCoreApplication::processEvents();
loop->start();
while(getchar() != '\n') QCoreApplication::processEvents();
loop->stop();
To copy to clipboard, switch view to plain text mode
(ReadLoopThread)
while(condition)
{
// read data from a serial device
// print data on console
// sleep 'x' miliseconds
}
while(condition)
{
// read data from a serial device
// print data on console
// sleep 'x' miliseconds
}
To copy to clipboard, switch view to plain text mode
What's the correct way to implement this?
I tried many solutions (none worked well):
1) create a thread with a timer that emits a signal every 'x' miliseconds (avoiding the use of sleep()) and connected to a slot that reads data from serial device and print data in console if a global boolean variable is 'true' (meaning Im on the "loop" command); not efficient - timer is always emitting the signal
2) two mutexes to control/block the loop as needed; it works but if I call QThread::sleep() it the thread blocks (why?)
Now Im thinking on using .moveToThread() of QObject class but I really need to control the periodicity of loop and that way I guess I can't use QThread::sleep().
The code in main():
int main(int argc, char *argv[])
{
Commander *commander = new Commander();
QObject::connect(commander,
SIGNAL(end
()),
&a,
SLOT(quit
()));
QTimer::singleShot(0, commander,
SLOT(start
()));
// start the thread QTimer::singleShot(10, commander,
SLOT(console
()));
// start console's loop
return a.exec();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Commander *commander = new Commander();
QObject::connect(commander, SIGNAL(end()), &a, SLOT(quit()));
QTimer::singleShot(0, commander, SLOT(start())); // start the thread
QTimer::singleShot(10, commander, SLOT(console())); // start console's loop
return a.exec();
}
To copy to clipboard, switch view to plain text mode
Commander inherits QThread. console() is the where I get (getline()) and parse user input.
The ReadLoopThread:
{
Q_OBJECT
public:
ReadLoop(Commander *commander) {m_commander = commander;}
public slots:
void run();
private:
Commander *m_commander;
};
class ReadLoop : public QThread
{
Q_OBJECT
public:
ReadLoop(Commander *commander) {m_commander = commander;}
public slots:
void run();
private:
Commander *m_commander;
};
To copy to clipboard, switch view to plain text mode
Control implemented with mutexes:
void ReadLoop::run()
{
forever
{
qDebug() << "readLoop is waiting to start";
start_mutex.lock();
start_mutex.unlock();
while(!stop_mutex.tryLock())
{
qDebug() << "readLoop'ing";
//QThread::sleep(1000); // DOESN'T WORK! Block the thread.
// Without it, qDebug() executes "as fast as possible" - not acceptable
}
stop_mutex.unlock();
}
}
void ReadLoop::run()
{
forever
{
qDebug() << "readLoop is waiting to start";
start_mutex.lock();
start_mutex.unlock();
while(!stop_mutex.tryLock())
{
qDebug() << "readLoop'ing";
//QThread::sleep(1000); // DOESN'T WORK! Block the thread.
// Without it, qDebug() executes "as fast as possible" - not acceptable
}
stop_mutex.unlock();
}
}
To copy to clipboard, switch view to plain text mode
Any help is GREATLY appreciated.
Bookmarks