Strange signal/slot behaviour - qt

(Working with Qt 5.15.2)
I have a method which receives a signal (sig_responseReady) from the same thread. The purpose of this method is to wait until a response is received. While this method is waiting for the signal, the method is called again because of an event which calls this method (so eventloops get nested). However, the first waitForResponse on the stack does not get the sig_responseReady signal for up to 10 seconds (for no reason I can see), while later called waitForResponse get their signal first.
The result of this design is that I have nested eventloops, which according to this stackoverflow post causes slot/signal handling errors, and should be avoided. I suspect this is the cause of my problem.
Is there a design which accomplishes the same, with only a single eventloop? (I can't come up with it) The function which calls waitForResponse must pause until waitForResponse returns. ..I can't make it asynchronous. I tried replacing eventloop.exec with QCoreApplication::processEvents(QEventLoop::AllEvents,100) in the function below, but still get same strange result. (So maybe nested event loops is not the problem...but I can't figure out the cause)
MyClass::SRequest MyClass::waitForResponse(const QUuid queryID) {
reentryCount++; // Static var to determing nesting/depth count
QEventLoop eventloop;
qDebug() << "MyClass::waitForResponse connect for uid " << queryID << ", depth " << reentryCount;
connect(this,&MyClass::sig_responseReady,&eventloop, &QEventLoop::quit); //, Qt::QueuedConnection); // Allow matching response to stop eventloop
do {
eventloop.exec();
qDebug() << "MyClass::waitForResponse got signal for uid " << queryID;
} while (!queryResponseReady(queryID) && !queryExpired(queryID));
qDebug() << "MyClass::waitForResponse exitted loop for signal for uid " << queryID << ", depth " << reentryCount;
reentryCount--;
return queryTakeResult(queryID);
}

Related

What is the reason asio doesn't do any delay?

I am new to asio.
Here is guide I was following writing my daytime tcp-server: https://think-async.com/Asio/asio-1.18.1/doc/asio/tutorial/tutdaytime3.html . I was trying to reproduce a reasonable example that would show that asunchronous code is actually asynchronous. I didn't modify anything else, just small piece of code in tcp_server class. I am adding this delay in order to see that after we are waiting timer to expire, we can gracefully handle other client connections/requests. So, did I miss something? Because in my case delay basically doesn't work ;(
void handle_accept(const tcp_connection::pointer &new_connection,
const asio::error_code &error) {
asio::steady_timer timer(io_context_, asio::chrono::seconds(5));
std::cout << "Before timer" << std::endl;
timer.async_wait(std::bind(&tcp_server::handle_wait, this, error, new_connection));
}
void handle_wait(asio::error_code &ec, const tcp_connection::pointer &new_connection) {
if (!ec) {
new_connection->start();
}
std::cout << "Inside timer" << std::endl;
start_accept();
}
void handle_accept(const tcp_connection::pointer &new_connection,
const asio::error_code &error) {
asio::steady_timer timer(io_context_, asio::chrono::seconds(5));
std::cout << "Before timer" << std::endl;
timer.async_wait(std::bind(&tcp_server::handle_wait, this, error, new_connection));
}
The timer is a local variable.
async_wait returns immediately, without blocking.
The function exits, destructing the timer. The timer cancels all pending operations (with error::operation_aborted).
🖛 Make sure the lifetime of the timer extends well enough to allow for it expire (or at least until it stops being relevant). In your case there will probably already be a tcp::acceptor member in your class, and the timer could reside next to it.

why QFuture::isFinished() ends early?

I have a question, I am trying to find the most simple way (without eventloop and or QFutureWatcher) to run a function in a different thread without blocking the gui. I have an exporter object from other library, can not change it, and its Close() function takes about 15 seconds to close.
So I tried this trick below but it works only for a couple of seconds, but then the processEvents() function blocks until the Export function is finished which makes it useless.
My Code:
QFuture<void> future = QtConcurrent::run([&]() {exporter.Close();
qDebug() << "closed!";});
while (!future.isFinished())
{
QApplication::processEvents();
QThread::msleep(1); //yield
qDebug() << "z";
}

QTimer slot triggered for multiple time?

I'm creating a UI application for Raspberry PI to read data from sensor on definite timeout (5 seconds). Problem is the QTimer timeout slot is called for multiple times
{ //at system init
readTempCur = new QTimer(this);
connect(readTempCur, SIGNAL(timeout()), this, SLOT(readSensor()));
readTempCur->start(SAMPLINGTIME);
readSensor(); //added to call on boot itself, can be removed
}
void HomePage::readSensor(void) {
readTempCur->stop();
qDebug() << "Read Sensor triggerred at " <<QDateTime::currentDateTime().toString();
//DO my actions
readTempCur->start(SAMPLINGTIME);
}
[edit for answer]
The most probable case for such issue is conneccting the slot to the signal that already conneccted; this will trigger slot for 'n' number times it got connected, design should take care not to reconnect again.
The QTimer::start function will start/restart the timer.
Your readSensor function stops the timer and then restart it again.
remove the start to fix it.
void HomePage::readSensor(void) {
readTempCur->stop();
qDebug() << "Read Sensor triggerred at " <<QDateTime::currentDateTime().toString();
//DO my actions
//readTempCur->start(SAMPLINGTIME);
}
P.S.
If you want to run the timer once you can use the singleShoot
QTimer::singleShot(SAMPLINGTIME, this, SLOT(readSensor()));
Do not stop nor restart the timer in readSensor(). Just do:
void HomePage::readSensor(void)
{
qDebug() << "Read Sensor triggerred at " <<QDateTime::currentDateTime().toString();
//DO my actions
}
Also, make sure SAMPLINGTIME is given in milliseconds. For 5 seconds, SAMPLINGTIME should be 5000.

If I reuse a QProcess variable, can there be leftover data in the stdout/stderr channels?

I have the following scenario:
QProcess*p;
// later
p->start();
//later
p->terminate(); // there might be unread data in stdout
//later
p->start();
I read the process stdout. After I call p->start() the second time, could there still be unread data left in the stdout buffers from the first p->start()? That would be a problem for me. Do I need to flush the buffers or something?
Okay, I've checked the sources. The QProcess::start() method explicitly clears both output buffers, so it should be okay, at least in this sense:
void QProcess::start(const QString &program, const QStringList &arguments, OpenMode mode)
{
Q_D(QProcess);
if (d->processState != NotRunning) {
qWarning("QProcess::start: Process is already running");
return;
}
#if defined QPROCESS_DEBUG
qDebug() << "QProcess::start(" << program << "," << arguments << "," << mode << ")";
#endif
d->outputReadBuffer.clear();
d->errorReadBuffer.clear();
I still think it's a bad style to reuse the same object, though.

qt - qprocess start in a loop

I am calling a process in a loop. Need to ensure that one process ends before it starts again. how is it possible.
void MainWindow::setNewProjectInQueueList()
{
// this is already gotten in queueList now loop thru the list and add project
QStringList arguments;
projNm = ui->lineEditCreateProject->text();
qDebug() << " projNm " << projNm;
for (int j= 0; j < queueList.length(); j++)
{ if (! QString(queueList[j]).isEmpty())
{
// call process
// QString queueName = queueList[j];
arguments << "-sq" << queueList[j];
qDebug() << " arguments sq " << queueList[j];
procQueueList.start("qconf",arguments);
}
}
// and append for each queue with new project name
// and store into the system
}
Brgds,
kNish
Call QProcess::waitForFinished() to wait until the process terminates.
Using the waitForFinished approach from within a loop in the main thread will freeze the application. Instead, putting the loop in a separate thread, or making a queue of processes to start and then launch upon the finished signal from the previous one is good alternatives.

Resources