How to put wait condition in Signal-Slot? - c++

I am doing one web related project. Recently I hit on this situation. This is just a stub
Class My_Class
{
public:
My_Class();
void start();
public slots():
void after_Load_Function();
}
My_Class::My_Class()
{
//Some initializations
connect(WebPage,SIGNAL(finished()),this,SLOTS(after_Load_Function()));
}
void My_Class::start()
{
WebPage->load();
}
void My_Class::after_Load_Function()
{
//Do something with the finished WebPage
}
int main(int argc,char * argv[])
{
//Some Qt things
My_Class a;
a.start();
}
"WebPage" emits the signal "finished" when it loaded fully.
Now the problem is before the "webPage" got loaded the "start" is returning. Thereby the control reaches the "main". So, now the control should return from "start" only after "after_Load_Function" finishes it's job. Thereby I want the below sequence,
main creates the My_Class object A.
main calls "start" from A.
start calls load from "WebPage" and it waits untill the "WebPage" emits "finished",
and that emit in turn calls the "after_Load_Function", and "after_Load_Function"
finishes it's job.
now, the "start" returns
main returns
But, I don't know how to make this kind of wait condition. How can I go about it?

You can do this by running a local event loop, letting the components process network income and load the page. When they emit the signal, you execute a slot on the event loop to quit it.
void My_Class::start()
{
QEventLoop qel;
QObject::connect(WebPage, SIGNAL(finished()), &qel, SLOT(quit()));
WebPage->load();
qel.exec();
}
I've been using this before and it works fine. I don't advice to use this too often though, because it will process events, including those that the caller of start might not be expecting to be processed during the call to start, so you need to document this to its callers. You can prevent the processing of some events by passing certain flags to QEventLoop::exec, like preventing to process user interface events.

You should never wait in UI code. You need to break your "main" function into pieces so the later part can be executed separately.

Use condition variables thats what they are used for. You can make threads wait on a condition variable and proceed when notified.

The WebPage->load() method is asynchronous, meaning that it runs immediately, not when the loading is complete. The operation runs in the background while you go to do other things.
This is considered a good thing, as it enables your app to be more responsive and get more done. For example, if your app has a GUI, you could update the GUI with some sort of animation that indicates that the web page is being retrieved.
If you prefer a model in which the application blocks until the page is fully loaded, then consider making this change:
void My_Class::start()
{
WebPage->load();
while (!WebPage->isLoaded())
Sleep(1);
after_Load_Function();
}
Notes:
the Sleep function will work on Windows. If you are on a Unix OS you can use usleep.
since this function will effectively block until the web page is loaded, there is no reason to use the signal from the web page object, you can just simply call your handler after the wait completes, as this will make your handler run in the same thread.
doing this is really bad practice. You may get away with it if your program is command line and has no GUI and/or event loop, but you should consider a better design for your app where the loading of web pages does not block the whole app.

Related

How to avoid freezing the user interface in a loop (minimal example) [duplicate]

My first naive at updating my progress bar was to include the following lines in my loop which is doing the processing, making something like this:
while(data.hasMoreItems())
{
doSomeProcessing(data.nextItem())
//Added these lines but they don't do anything
ui->progressBar->setValue(numberProcessed++);
ui->progressBar->repaint();
}
I thought adding the repaint() would make the execution pause while it updated the GUI, but apparently it's not that simple. After looking at the questions:
QProgressBar Error
Progress bar is not showing progress
it looks like I'm going to have to put the data processing in a different thread and then connect a signal from the data processing thread to the GUI thread to update the progressbar. I'm rather inexperienced with GUIs and threads and I was wondering if anyone could just point me in the right direction, ie what Qt classes should I be looking at using for this. I'd guess I need a QThread object but I've been looking through the QProgressBar documentation but it doesn't bring up the topic of threading.
As #rjh and #Georg have pointed out, there are essentially two different options:
Force processing of events using QApplication::processEvents(), OR
Create a thread that emits signals that can be used to update the progress bar
If you're doing any non-trivial processing, I'd recommend moving the processing to a thread.
The most important thing to know about threads is that except for the main GUI thread (which you don't start nor create), you can never update the GUI directly from within a thread.
The last parameter of QObject::connect() is a Qt::ConnectionType enum that by default takes into consideration whether threads are involved.
Thus, you should be able to create a simple subclass of QThread that does the processing:
class DataProcessingThread : public QThread
{
public:
void run();
signals:
void percentageComplete(int);
};
void MyThread::run()
{
while(data.hasMoreItems())
{
doSomeProcessing(data.nextItem())
emit percentageCompleted(computePercentageCompleted());
}
}
And then somewhere in your GUI code:
DataProcessingThread dataProcessor(/*data*/);
connect(dataProcessor, SIGNAL(percentageCompleted(int)), progressBar, SLOT(setValue(int));
dataProcessor.start();
You need to call QApplication::processEvents() periodically inside your processing loop to let it handle UI events.
As Georg says, Qt is a single-threaded co-operative multitasking environment. You get full control of your process until you relinquish it voluntarily with processEvents() - until you do that, Qt can't update the UI elements, handle async HTTP requests, handle input, or pretty much anything else. It's up to you to make sure that stuff gets a timeslice while you're in a long processing loop.
You can create a sub-class of QThread that emits a signal progressChanged, which you connect to the QProgressBar.
connect() makes the connections auto connections per default. That means that the signal-slot-mechanism already takes care of the threading issues for you, so you don't need to worry about that.

What does QTimer::singleShot(0, object SLOT(obj_slot())) do?

I'm beginner learning Qt, and trying to understand a Qt provided example for download operation. In downloadmanager.cpp, a member function is the following:
void DownloadManager::append(const QUrl &url)
{
if (downloadQueue.isEmpty())
QTimer::singleShot(0, this, SLOT(startNextDownload()));
downloadQueue.enqueue(url);
++totalCount;
}
I'm confused to why, if downloadQueue is empty, it will need to activate the startNextDownload() before adding the url. (note that: startNextDownload() ends the program if the downloadQueue is empty)
I'm unsure why: QTimer::signleShot(x, y, z) has been used at all. As I understand it to be, a timer that activates the slot with delay of 0 millisecond.
I could not figure out from looking at Qt Assistant whether singleShot is a one time setup for repeated activation to the slot at given millisecond interval or whether it is one time
Clarification:
I'm a beginner and in examples like:
statement1;
statement2;
I'm used to seeing statement1 running and finishing before moving on to working on statement2. But trying to learn Qt and reading the given example, I see the SLOT(startNextDownload()) being activated after downloadQueue.enqueue(url); has taken place. I am trying to understand why does this work.
This queues a callback in the message queue.
The timer immediately elapses, and a message is posted to the message queue. When the process reaches the main loop for the next time, the startNextDownload() function is called. By this time, the URL is in the queue.
The startNextDownload() function is called from the dispatch context, where it is safe to change window contents. This way, the DownloadManager class can be used from a multithreaded application, where the thread starting the download might be running concurrently with the handler for a Paint event. By invoking it from the same thread that would handle Paint events you can be sure that no such event is being processed, and you can update widgets safely.
If a widget needs to be repainted afterwards, it then asks to be repainted, and the OS will send a Paint event if the widget is currently visible.
Answer to current question title
Every call to QTimer::singleShot(...) is executed on the event loop of the thread where it is invoked **. If invoked from the main thread, it'll be the event loop started with app.exec().
According to the Qt-Network-Manager-Example, this function is called after the network-manager is filled with the URL's so the single-shot will be processed after the queue has been completely filled. Poorly the qt documentation isn't that clear about this topic yet, so for more information about event processing etc please look here.
Answer for old question title
Before I start, the timer is for having the download in an extra thread. So the GUI keeps responsive.
The complete downloadNext() method is recursive. It will be only called once and called till the queue is empty.
See this:
void DownloadManager::append(const QStringList &urlList)
{
foreach (QString url, urlList)
append(QUrl::fromEncoded(url.toLocal8Bit())); //Call for only one URL
...
}
void DownloadManager::append(const QUrl &url)
{
if (downloadQueue.isEmpty())
//I'm only called if the queue is empty! And I will be called after the next line. Not instantly!
QTimer::singleShot(0, this, SLOT(startNextDownload()));
downloadQueue.enqueue(url);
++totalCount;
}
After the queue is empty each method returns and at least the message that the download is done will be printed.
So why does this work?
Please see first chapter below.
you can understand things about Class QTimer before you end up with a solution as you desire, please have a look here for your understanding

QT - force an object to process incoming signals

I am wondering how to tell a QObject to process all signals and call the slots associated with them. Here's the concrete problem I am having, for a better description of the question:
My program consists of three Qthreads : Main, Communication and Input.
The communication thread handles communication via the network, the Input thread handles user input, and both have several signal-slot connections to the main thread. Whenever a network event occurs, or whenever the user inputs a commandline command, a signal from the respective thread is called, which then activates the appropriate connected slot in the main thread. The main thread's role is to process these events. My code looks as follows:
QApplication a(argc, argv);
CommObj co; //inherits from QThread
co.start(); //Starts the thread
InputObj io; //inherits from QThread
io.start(); //Starts the thread
MainObj u(&co,&io);
return a.exec();
Now, what I want to achieve is for the main thread to not reach the last line.
My intentions are to call a method run() within the constructor of MainObj which is going to do something along the lines of this:
void run ()
{
forever
{
//process all signals..
}
}
However, I do not know how to implement the process all signals part. Any advice on how this could be done (including workarounds) would be very welcome.
This is completely unnecessary. a.exec() runs an event loop that will receive and process the events sent by other threads.
When a slot is invoked due to a signal being emitted in a different thread, Qt is posting a QMetaCallEvent to the receiver object. The QObject::event method is able to re-synthesize the slot call based on the data in the event.
Thus, you need to do nothing. a.exec() does what you want. Feel free to invoke it from MainObj's constructor, as qApp->exec() or as QEventLoop loop; loop.exec(), but that's rather bad design.
The real questions are:
Why do you need MainObj's constructor to spin an event loop?
What sort of "user input" are you processing in the io? You can't access any GUI objects from that thread.
Why are you deriving from QThread if you're using Qt's networking? You definitely don't want to do that - it won't work unless you spin an event loop, so you might as well just use a QThread without changes. Well, to be safe, you need just to make the thread destructible, so:
class Thread {
using QThread::run; // make it final
public:
Thread(QObject * parent = 0) : QThread(parent) {}
~Thread() { requestInterruption(); quit(); wait(); }
};
Anyway, by not using standard QThread that spins an event loop, the communication will be one way. Nothing in such threads will be able to react to signals from other threads.
You need to rearchitect as follows:
Use the Thread class as above. It's safe to be destructed at any time.
Have worker objects that run asynchronously using signals/slots/timers.
Move constructed workers to their threads.
What you need is the processEvents function. For example, if you don't want the user to be able to interact with widgets, but you want the graphics to update, use
processEvents(QEventLoop::ExcludeUserInputEvents);
See the documentation for details.

Qt/C++ how to wait a slot when signal emitted

I have developed an app in Qt/C++, I have used signal/slot mechanism to interact between 2 threads. the first thread run the UI/TreeWidget and the second one run the framework
I got an issue on one action.
In the UI side, before starting my action, I'm connect signal/slot between UI and framework such as below in the treewidget.cpp
connect(&m_Framework, &Framework::RequestIfNameExist, this, &TreeWidget::RequestIfNameExist);
connect(this, &TreeWidget::SendAnswerIfNameExist, &m_Framework, &Framework::NotifIfNameExist);
The framework, start and send the RequestIfNameExist:
emit RequestIfNameExist(tmpname, item, fileInfo.isDir());
while(WaitingResponse == false){
usleep(200);
}
I have added a loop because I need to wait the feedback. Strange things is that in the treewidget.cpp, I never enter in
void TreeWidget::RequestIfNameExist(QString name, TreeWidgetItem *parent, bool isFolder) {
#ifdef PULS_LOG
QLOG_INFO() << "[TreeWidget] [RequestIfNameExist] ";
#endif
emit SendAnswerIfNameExist(isNameExist(name, parent), isFolder);
}
I never access to RequestIfNameExist in the TreeWidget but the signal is emitted.
I have also put a while loop in the framework to wait the feedback from TreeWidget
void Framework::NotifIfNameExist(QTreeWidgetItem *item, bool isFolder){
if(item != NULL)
item->isFolder = isFolder;
WaitingResponse = true;
}
Any idea why the signal emitted by framework never arrived on the treewidget ? is it coming from the while ??
Is there a way to not use while such as a "wait event" + timeout
Thanks
My first thought is that having either thread block until an operation in the other thread completes is a poor design -- it partially defeats the purpose of having multiple threads, which is to allow multiple operations to run in parallel. It's also liable to result in deadlocks if you're not careful (e.g. if both threads decide to emit-and-wait at approximately the same time!)
A better design would have the initiating method do the emit RequestIfNameExit and then return immediately, so that the initiating thread's event loop can continue running as usual during the operation. Then, when the other thread has done its work, it responds by emitting its own response-signal, causing the appropriate/connected slot-method in the first thread to be called, at which point the results are handled back in the first thread.
That said, if you insist on wanting to block the execution of the signal-emitting thread inside a method, until the other thread has finished executing the associated slot-method, you can get that behavior by setting the signal/slot connection's type to be Qt::BlockingQueuedConnection (the connection type can be specified via an optional extra argument to connect()). If you do that, then you emit call won't return until the slot-method (in the other thread) has finished executing. Given that, you can get the results from the other thread by passing a pointer to a data object as one of the arguments in the signal/slot method signature, and having the other thread populate that data object as necessary. When the emit returns you can just examine the contents of that data object to see the results.

Qt Programming and computations which take long time

I am new on Qt programming. I have to make some computations which take long time. I use an edit box and two button named as "start" and "stop". The edit box is used for the initialization. Start button starts the computation. While the computation is going on, I must be able to stop the computation whenever I want. But when I start the computation by clicking the start button. As expected, I cannot click any component on the window until the computation is completed.
I want to use the components (especially stop button) on the window normally while the computation is performing. But I am not good on the threads, I am looking for an easier method. Is there any simple solution?
There are a couple of options.
1. Subclass QRunnable
Subclass QRunnable and use QThreadPool to run it in a separate thread. To communicate with the UI, use signals. Example of this:
class LongTask: public QRunnable
{
void run()
{
// long running task
}
};
QThreadPool::globalInstance()->start(new LongTask);
Note that you don't need to worry about managing the thread or the lifetime of your QRunnable. For communicating, you can connect your custom signals before starting the QRunnable.
2. Use QtConcurrent::run
This is a different approach and might not suit your problem. Basically, the way it works is the following: you get a handle to the future return value of the long task. When you try to retrieve the return value, it will either give it to you immediately or wait for the task to finish if it hasn't already. Example:
QFuture<int> future = QtConcurrent::run(longProcessing, param1, param2);
// later, perhaps in a different function:
int result = future.result();
3. Subclass QThread
You probably don't need this, but it isn't hard either. This one is very similar to #1 but you need to manage the thread yourself. Example:
class MyThread : public QThread
{
public:
void run()
{
// long running task
}
};
QThread* thread = new MyThread(this); // this might be your UI or something in the QObject tree for easier resource management
thread.start();
Similarly to QRunnable, you can use signals to talk to the UI.
In your computation you can put QCoreApplication::processEvents(); so that GUI events also get processed. This will omit usage of threads.
You can have your computation occur in a different thread than your GUI. When the GUI recieves a signal that the stop button is pressed, you change a flag value which your computation thread periodically checks. When the flag is set, you can terminate the computation thread.
Either use threads (perhaps synchronizing them by sending messages on pipes to self), or use timer (with a 0 millisecond delays, this is how idle processing is done in Qt).