PDA

View Full Version : Qt Console Application: while loop blocks event loop



msr
5th August 2011, 15:28
Hello,

Im making a console application where Im getting user input with std::getline() (in a while loop). Im also using QextSerialPort (inherits QIODevice) and readyRead() signal. Thus I need an event loop so I'm using QCoreApplication and calling a.exec().

The problem is getline() blocks event loop and, while it's blocked, I can't receive anything from serial port. I tried to use QCoreApplication::processEvents() in the while(1){getline()} loop, but found that's not a good solution. Then, I tried to call QCoreApplication::processEvents() in a QThread but it didn't work.

Here's the code Im using:


int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

Base *base = new Base();
Commander *commander = new Commander(base);

QObject::connect(commander, SIGNAL(end()), &a, SLOT(quit()));
QTimer::singleShot(0, commander, SLOT(run()));

return a.exec();
}


void Commander::askToConnect()
{
if(base->connect() == false){
cout << "Failed to open port." << endl;
}
}

void Commander::run{
string inputline;

askToConnect();

while(1){
QCoreApplication::processEvents(); // ???

cout << endl << "> ";
getline(cin, inputline);

// ...
}
}

Even if I have while(1); the event loop is blocked and I can't read data from serial port.

So, how can I get user input without blocking event loop?

Thanks!

MarekR22
5th August 2011, 15:49
This is drawback of using standard console. There is no easey solution.

yeye_olive
5th August 2011, 15:53
Blocking input routines such as getline() block the thread which runs them. I see two options:
1. Move all the input on stdin to a dedicated thread that will send each read line to the main thread (e.g. using signals and slots). Tip: if you need to exit the application, I guess you can close stdin to make the thread return from the blocking call.
2. Use non-blocking input on stdin. This will be trickier and highly platform-dependant. Libraries such as ncurses might help you here.

I would recommend using solution 1.

wysota
5th August 2011, 17:25
Use a QSocketNotifier on stdin and query input only when there is something to read.

msr
6th August 2011, 02:40
Blocking input routines such as getline() block the thread which runs them. I see two options:
1. Move all the input on stdin to a dedicated thread that will send each read line to the main thread (e.g. using signals and slots). Tip: if you need to exit the application, I guess you can close stdin to make the thread return from the blocking call.
2. Use non-blocking input on stdin. This will be trickier and highly platform-dependant. Libraries such as ncurses might help you here.

I would recommend using solution 1.

yeye_olive, I sticked with the first option. getline() is now in a dedicated thread and I send the "inputline" through a signal. It's working!

Thank you all for your help!