c++ - 如何从一个线程的结果中返回一个 Qt 对象 (Qtfutur)

标签 c++ multithreading qt blackberry-10

我正在尝试从服务器加载一些数据并填充 Qt 列表。我想在线程中运行下载。所以有以下代码:

  • App.cpp

    中的主要函数
    loadInterestPlaces(QString& urlInterestPlaces) {
    LoadData* Data = new LoadData(urlInterestPlaces);
    
    QFuture< list <InterestPlace *> > future = QtConcurrent::run(Data,
            &LoadData::startLoading);
    
    
    
    // Invoke our onLoadingFinished slot after the loading has finished.
    bool ok = connect(&m_watcher, SIGNAL(finished()), this,
            SLOT(onLoadingFinished()));
    Q_ASSERT(ok);
    Q_UNUSED(ok);
    
    // starts watching the given future
    m_watcher.setFuture(future);
    
    }
    
    void ApplicationUI::onLoadingFinished() {
    qDebug() << "Loading finished";
    
    
    interestPlacesList = m_watcher.future().result();
    qDebug() << "List size= " << interestPlacesList.size();
    
        }
            }
    
  • LoadData.cpp 文件:这是启动加载函数的代码:

    std::list<InterestPlace *> LoadData::startLoading()
    {
    QNetworkAccessManager* netManager = new QNetworkAccessManager(this);
    
    const QUrl url(_URL);
    QNetworkRequest request(url);
    
    QNetworkReply* reply = netManager->get(request);
    
    netManager->moveToThread(this->thread());
    netManager->setParent(this);
    
    bool ok = connect(reply, SIGNAL(finished()), this, SLOT(onReplyFinished()));
    qDebug() << reply->isFinished();
    Q_ASSERT(ok);
    Q_UNUSED(ok);
    
    qDebug() << "load data: liste size" <<interestPlacesList.size();
    return interestPlacesList;
    }
    

最后在 SLOT onreplyfinished 中,我解析数据并填充列表。 但这里的问题是,QFuture 在下载之前就完成了,所以列表总是空的。 我怎样才能返回在 onReplyFinished 执行后立即填充的列表?

最佳答案

您可能会把它变得比您需要的更复杂。这是我从网上获取数据的方法。在我的例子中,我正在下载一个大的 ZIP 文件,将其写出来然后解压缩,但基本步骤是相同的​​(为清楚起见,我省略了很多具体代码):

void HtmlDownloader::startDownload() {
    // Creates the network request and sets the destination URL
    QNetworkRequest request = QNetworkRequest();
    request.setUrl(mUrl);

    // Creates the network access manager and connects a custom slot to its
    // finished signal. Checks the return value for errors.
    QNetworkAccessManager *networkAccessManager =
            new QNetworkAccessManager(this);
    bool c = connect(networkAccessManager, SIGNAL(finished(QNetworkReply*)),
            this, SLOT(requestFinished(QNetworkReply*)));

    Q_ASSERT(c);

    // Indicate that the variable res isn't used in the rest of the app, to prevent
    // a compiler warning
    Q_UNUSED(c);

    // Sends the request
    QNetworkReply *reply = networkAccessManager->get(request);

    c = connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(onDownloadProgress(qint64,qint64)));
    Q_ASSERT(c);

}

void HtmlDownloader::requestFinished(QNetworkReply *reply) {
// Handle the reply data...
// Check the network reply for errors
    if (reply->error() == QNetworkReply::NoError) {
        // use reply->readAll() or reply->read() to get the returned data
        // and process into a list. The list can't be returned but could
        // be sent as a payload of a signal, or stored in a data member and
        // a signal sent to indicate it is available.
    }
    reply->deleteLater();
}

void HtmlDownloader::onDownloadProgress(qint64 bytesRecieved, qint64 bytesTotal) {
    emit downloadProgress(bytesRecieved, bytesTotal);
}

关于c++ - 如何从一个线程的结果中返回一个 Qt 对象 (Qtfutur),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20046052/

相关文章:

c++ - 带有动态添加的小部件的 QScrollArea

c++ - 如何在 Linux (Ubuntu) 中调整 Qt Creator for VTune Amplifier

c++ - std::map::emplace 语法问题

c++ - Visual Studio C++ 项目中所需的 DLL

c++ - 递增预处理器宏

java - 我如何为执行程序选择线程数

multithreading - std::map 在 c++11 中插入线程安全吗?

c++ - 从 Ubuntu 运行一个可执行文件到 Debian

java - 了解生成线程的类上的线程和同步

c++ - 如何在Qt中运行纯c++程序?