QTimer :: singleShot(0,对象SLOT(obj_slot()))做什么?

时间:2017-01-07 17:20:17

标签: c++ qt qt4

我是初学者学习Qt,并尝试了解提供example的Qt进行下载操作。在downloadmanager.cpp中,成员函数如下:

void DownloadManager::append(const QUrl &url)
{
    if (downloadQueue.isEmpty())
        QTimer::singleShot(0, this, SLOT(startNextDownload()));

    downloadQueue.enqueue(url);
    ++totalCount;
}
  • 我很困惑为什么,如果downloadQueue为空,则需要在添加网址之前激活startNextDownload()(请注意:如果startNextDownload()为空,downloadQueue会结束该计划
  • 我不确定原因:QTimer::signleShot(x, y, z)已被使用过。据我所知,一个定时器以0毫秒的延迟激活插槽。
  • 我无法从查看Qt助手中弄清楚singleShot是否是以给定的毫秒间隔重复激活到插槽的一次性设置,或者是否是一次

澄清:

我是初学者,例如:

statement1;
statement2;

我常常看到statement1正在运行和完成,然后继续工作statement2。但是,尝试学习Qt并阅读给定的示例,我看到SLOT(startNextDownload())downloadQueue.enqueue(url);发生后被激活。我试图理解为什么这样做。

3 个答案:

答案 0 :(得分:2)

这会在消息队列中对回调进行排队。

计时器立即过去,并将消息发布到消息队列中。当进程下次到达主循环时,将调用startNextDownload()函数。到这时,URL就在队列中。

从调度上下文调用startNextDownload()函数,可以安全地更改窗口内容。这样,DownloadManager类可以在多线程应用程序中使用,其中开始下载的线程可能与 Paint 事件的处理程序同时运行。通过从处理 Paint 事件的同一线程调用它,您可以确保没有处理此类事件,并且可以安全地更新窗口小部件。

如果之后需要重新绘制窗口小部件,则会要求重新绘制,如果窗口小部件当前可见,操作系统将发送 Paint 事件。

答案 1 :(得分:0)

回答当前的问题标题

QTimer::singleShot(...)的每次调用都在调用它的线程的事件循环上执行 **。如果从主线程调用,它将是以app.exec()开头的事件循环。

根据Qt-Network-Manager-Example,在网络管理器填充了URL后,此函数被称为,因此在队列完全填满后将处理单击。 qt文档还不是很清楚这个主题,所以有关事件处理等的更多信息,请查看here

回答旧问题标题

在开始之前,计时器用于在额外的线程中进行下载。因此,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;
}

队列为空后,每个方法都会返回,并且至少会打印下载完成的消息。

那为什么会这样呢? 请参阅下面的第一章。

答案 2 :(得分:0)

在您根据需要找到解决方案之前,您可以了解有关QTimer课程的信息,please have a look here for your understanding