Qt中的异步函数调用

时间:2014-11-19 22:22:11

标签: c++ qt asynchronous

我对Qt和编程很新,并且遇到了一个我无法找到解决方案的问题。

我想从在线XML文件中读取一些信息并将其发送到我的主程序。

为此,我创建了一个XMLParser类,并将以下内容添加到构造函数中:

XMLParser::XMLParser(QString searchstring)
{
    QNetworkAccessManager *manager2 = new QNetworkAccessManager(this);
    reply = manager2->get(QNetworkRequest(QUrl("http://www.boardgamegeek.com/xmlapi/search?search="+searchstring)));

    XMLParser::connect(reply, SIGNAL(finished()),
                   this, SLOT(fileIsReady()) );
}

fileIsReady填充QMap并将其存储为私有类成员。

在我的第二节课中,我打电话给

  XMLParser *xmlpars = new XMLParser(input_gamename->text());
  QMap<QString, int> searchResults = xmlpars->getSearchList();

和getSearchList是一个简单的getter函数。

问题是,在fileIsReady完成读取XML文件并返回空映射之前执行getSearchList。 据我所知,构造函数不应该在fileIsReady()完成工作之前完成。因此,不应该提前调用getSearchList()。

我的两个问题:

  1. 为什么我的程序在功能没有完成阅读时进展。
  2. 如何进行第二次通话&#34; getSearchList&#34;等待?
  3. 提前多多感谢!

3 个答案:

答案 0 :(得分:3)

首先,您需要了解信号和插槽的基本概念。

进行连接后,每次发出信号时都会调用插槽。

将信号连接到插槽后,connect()函数返回。它不会等待发出信号。

在您的XMLParser构造函数中,您的connect()函数会注册:&#34;当发出finished()信号时,运行fileIsReady()函数&#34;。

现在,回答你的问题。

  
      
  1. 为什么我的程序在功能没有完成阅读时进展。
  2.   

因为在构造函数代码中,在将信号连接到插槽后要求构造函数完成。您没有要求它等待下载完成。

然后,在不等待finished()信号的情况下调用getSearchList()。因此,在fileIsReady()之前调用getSearchList()。

  
      
  1. 如何进行第二次通话&#34; getSearchList&#34;等待?
  2.   

就像MrEricSir所说,你不应该让它等待! (想想看:如果你失去了互联网连接并且无法完成下载文件会怎么样?答案是,你的程序会冻结,因为它会永远等待。这很糟糕。)

构建XMLParser后不要立即调用getSearchList()。相反,让XMLParser发出一个&#34; finishedParsing()&#34;完成解析XML文件时发出信号。然后,进行另一个信号槽连接:将finishedParsing()信号连接到调用getSearchList()的插槽。

答案 1 :(得分:1)

  

如何进行第二次电话getSearchList等待?

你不是!相反,只需将期望XML文件的任何代码移动到您已定义的fileIsReady()广告位中。这样,你的程序在等待下载完成时就不会锁定(这是异步编程的全部内容。)

答案 2 :(得分:1)

所以,我找到了一个使用QEventLoop的解决方案。但就我而言,这并不值得推荐。 还有其他解决方案吗?为什么使用QEventLoop的坏习惯(这是我从StackOverflow的其他答案中读到的)。

XMLParser::XMLParser(QString searchstring)
{

QNetworkAccessManager *manager2 = new QNetworkAccessManager(this);
reply = manager2->get(QNetworkRequest(QUrl("http://www.boardgamegeek.com/xmlapi/search?search="+searchstring)));

QEventLoop loop;
XMLParser::connect(reply, SIGNAL(finished()),
                   this, SLOT(fileIsReady()) );
XMLParser::connect(this, SIGNAL(finishedReading()),
                   &loop, SLOT(quit()));
loop.exec();

}