[英]What does QTimer::singleShot(0, object SLOT(obj_slot())) do?
我是初学者学习Qt,并尝试理解Qt提供的下载操作示例 。 在downloadmanager.cpp中 ,成员函数如下:
void DownloadManager::append(const QUrl &url)
{
if (downloadQueue.isEmpty())
QTimer::singleShot(0, this, SLOT(startNextDownload()));
downloadQueue.enqueue(url);
++totalCount;
}
downloadQueue
为空,则需要在添加url之前激活startNextDownload()
。 (注意:如果downloadQueue
为空,则startNextDownload()
结束程序) QTimer::signleShot(x, y, z)
已经被使用了。 据我所知,一个定时器以0毫秒的延迟激活插槽。 我是初学者,例如:
statement1;
statement2;
我已经习惯了看到statement1
上移动到上工作前,运行和整理statement2
。 但是尝试学习Qt并阅读给定的例子,我看到在downloadQueue.enqueue(url);
之后激活了SLOT(startNextDownload())
downloadQueue.enqueue(url);
已经发生了。 我试图理解为什么这样做。
这会在消息队列中对回调进行排队。
计时器立即过去,并将消息发布到消息队列中。 当进程下次到达主循环时,将startNextDownload()
函数。 此时,URL位于队列中。
从调度上下文调用startNextDownload()
函数,可以安全地更改窗口内容。 这样,可以从多线程应用程序中使用DownloadManager
类,其中开始下载的线程可能与Paint事件的处理程序同时运行。 通过从处理Paint事件的同一线程调用它,您可以确保没有处理此类事件,并且可以安全地更新窗口小部件。
如果之后需要重新绘制窗口小部件,则会要求重新绘制,如果窗口小部件当前可见,操作系统将发送Paint事件。
每次调用QTimer::singleShot(...)
都会在调用它的线程的事件循环上执行**。 如果从主线程调用,它将是用app.exec()
启动的事件循环。
根据Qt-Network-Manager-Example,在网络管理器填充URL 之后调用此函数,以便在队列完全填满后处理单击。 qt文档还不是很清楚这个主题,所以有关事件处理等的更多信息,请看这里 。
在我开始之前,计时器用于在额外的线程中进行下载。 因此GUI保持响应。
完整的downloadNext()
方法是递归的。 它只会被调用一次并被调用,直到队列为空。 看到这个:
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;
}
队列为空后,每个方法都返回,并且至少会打印下载完成的消息。
那么为什么这样呢? 请参阅下面的第一章。
在您最终获得所需的解决方案之前,您可以了解有关QTimer课程的信息, 请在此处查看以获取您的理解
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.