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;
}
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)
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'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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With