首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在使用QCoreApplication和QThread的QT中正确关闭QtNetwork?

如何在使用QCoreApplication和QThread的QT中正确关闭QtNetwork?
EN

Stack Overflow用户
提问于 2021-02-26 10:31:45
回答 1查看 107关注 0票数 0

我正在尝试创建一个QT,以便在InnoSetup安装程序中使用它(InnoSetup是用Delphi编写的)。

当从InnoSetup调用时,这个DLL应该具有从因特网下载文件的功能。

InnoSetup调用如下所示:

代码语言:javascript
复制
procedure downloadFile();
  external 'doDownload@files:testdll.dll,libssl-1_1.dll,libcrypto-1_1.dll stdcall loadwithalteredsearchpath delayload';

然后,我称它为:

代码语言:javascript
复制
function InitializeSetup(): Boolean;
begin
  Result := True;
  ExtractTemporaryFile('testdll.dll');
  downloadFile();
end;

downloadFile();的问题是,如果我需要稍后(在初始调用之后)调用它,我就不能重用它,因为在第一次调用时,不知何故,怀疑没有正确关闭,仍然处于执行循环中。当我第二次调用这个函数时,什么都没有发生,没有文件从互联网上下载。再次下载文件的唯一方法是关闭并重新打开Inno安装程序。

这是我的密码:

TESTDLL.pro

代码语言:javascript
复制
QT -= gui
QT += network

TEMPLATE = lib
DEFINES += TESTCLASS_LIBRARY

CONFIG += c++11 dll

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    testdll.cpp \
    libs\downloadThread.cpp

HEADERS += \
    testdll_global.h \
    testdll.h \
    libs\downloadThread.h

QMAKE_LFLAGS += -Wl,--output-def,testdll.def

# Default rules for deployment.
unix {
    target.path = /usr/lib
}
!isEmpty(target.path): INSTALLS += target

TESTDLL.h

代码语言:javascript
复制
#ifndef TESTDLL_H
#define TESTDLL_H

#include <QtCore>

#include "testdll_global.h"
#include "libs/downloadThread.h"


class TestDLL : public QObject
{
    Q_OBJECT
public slots:
    void handleResults(const QString &);
    void startWThread();
    void initQCoreApp();

private:
    void debugMsg(QString fileName, QString message)
    {
        QFile file(fileName);
        file.open(QIODevice::WriteOnly | QIODevice::Text);
        QTextStream out(&file);
        out << message;
        file.close();
    };
};

#endif

TESTDLL.cpp

代码语言:javascript
复制
#include "testdll.h"

namespace QCoreAppDLL
{
    static int argc = 1;
    static char arg0[] = "testdll.cpp";
    static char * argv[] = { arg0, nullptr };
    static QCoreApplication * pApp = nullptr;
}

extern "C" TESTCLASS_EXPORT void doDownload()
{
    TestDLL a;
    a.initQCoreApp();
}

void TestDLL::startWThread()
{
    downloadThread *thread = new downloadThread(this);
    connect(thread, &downloadThread::finished, thread, &QObject::deleteLater);
    connect(thread, &downloadThread::resultReady, this, &TestDLL::handleResults);
    thread->start();
}

void TestDLL::initQCoreApp()
{

    if (!QCoreApplication::instance())
    {
        QCoreAppDLL::pApp = new QCoreApplication(QCoreAppDLL::argc, QCoreAppDLL::argv);

        TestDLL a;
        a.startWThread();

        QCoreAppDLL::pApp->exec();
    }
}

void TestDLL::handleResults(const QString &)
{
    debugMsg("result.txt","succes!");

    if (QCoreAppDLL::pApp)
        QCoreAppDLL::pApp->quit();
}

DOWNLOADTHREAD.h

代码语言:javascript
复制
#ifndef downloadThread_H
#define downloadThread_H

#include <QtNetwork>
#include <QDebug>

class downloadThread : public QThread
{
    Q_OBJECT
signals:
    void resultReady(const QString &s);
public:
    downloadThread(QObject *parent);
    ~downloadThread();

    void run() override {
        QString result;

        initDownload();

        emit resultReady(result);
    };
    void initDownload();
    void doDownload(QString url);
private:
    QNetworkAccessManager *networkMgr;
    QNetworkReply *_reply;
public slots:
  void replyFinished(QNetworkReply * reply);
};
#endif

DOWNLOADTHREAD.cpp

代码语言:javascript
复制
#include "downloadThread.h"

downloadThread::downloadThread(QObject *parent)
    : QThread(parent)
{
}

downloadThread::~downloadThread()
{
   quit();
   wait();
}

void downloadThread::initDownload()
{
    doDownload("http://www.google.com");
    exec();
}

void downloadThread::doDownload(QString url)
{
    networkMgr = new QNetworkAccessManager;

    QNetworkRequest request;
    request.setUrl(QUrl(url));
    networkMgr->get(request);

    connect(networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
}

void downloadThread::replyFinished(QNetworkReply * reply)
{
    if(reply->error() == QNetworkReply::NoError)
    {
        QByteArray content = reply->readAll();
        QSaveFile file("output.txt");
        file.open(QIODevice::WriteOnly);
        file.write(content);
        file.commit();

        reply->deleteLater();
        this->exit();
    } else {
        //error
        reply->deleteLater();
        this->exit();
    }
}

为了解决这个问题,我自己尝试过的工具:

  • 使用删除QCoreAppDLL::pApp

代码语言:javascript
复制
void TestDLL::handleResults(const QString &)
{
    debugMsg("result.txt","succes!");

    if (QCoreAppDLL::pApp){
        QCoreAppDLL::pApp->quit();
        delete QCoreAppDLL::pApp;
    }
}

正在破坏主机应用程序。

SLOT(quit()),和QTimer的使用

代码语言:javascript
复制
void TestDLL::initQCoreApp()
{

    if (!QCoreApplication::instance())
    {
        QCoreAppDLL::pApp = new QCoreApplication(QCoreAppDLL::argc, QCoreAppDLL::argv);

        TestDLL a;

        connect(&a, SIGNAL(finished()), QCoreAppDLL::pApp, SLOT(quit()));
        QTimer::singleShot(0, &a, SLOT(startWThread));

        QCoreAppDLL::pApp->exec();
    }
}

什么都没有发生,就像QCoreApplication执行循环在QThread完成任务之前就结束了。

  • 在QThread对象

上使用插槽/信号

代码语言:javascript
复制
void TestDLL::startWThread()
{
    downloadThread *thread = new downloadThread(this);
    connect(thread, &downloadThread::finished, thread, &QObject::deleteLater);
    connect(thread, &downloadThread::resultReady, this, &TestDLL::handleResults);
    connect(thread, SIGNAL(finished()), qApp, SLOT(quit()));
    thread->start();
}

具有与以下行为相同的行为:

代码语言:javascript
复制
void TestDLL::handleResults(const QString &)
{
    debugMsg("result.txt","succes!");

    if (QCoreAppDLL::pApp)
        QCoreAppDLL::pApp->quit();
}

我没有主意了,我还能做些什么来解决这个问题呢?

谢谢,伙计们!

EN

回答 1

Stack Overflow用户

发布于 2021-02-26 18:28:43

我终于自己解决了这个问题。这是给那些感兴趣的人的。

我创建了一个新功能:

代码语言:javascript
复制
void TestDLL::deinitQCoreApp()
{
    if (QCoreAppDLL::pApp)
        delete qApp;
}

现在,我的外部功能变成:

代码语言:javascript
复制
extern "C" TESTCLASS_EXPORT void doDownload()
{
    TestDLL a;
    a.initQCoreApp();

    TestDLL b;
    b.deinitQCoreApp();
}

当然,TESTDLL.h有一个新条目:

代码语言:javascript
复制
#ifndef TESTDLL_H
#define TESTDLL_H

#include <QtCore>

#include "testdll_global.h"
#include "libs/downloadThread.h"


class TestDLL : public QObject
{
    Q_OBJECT
public slots:
    void handleResults(const QString &);
    void startWThread();
    void initQCoreApp();
    void deinitQCoreApp();

private:
    void debugMsg(QString fileName, QString message)
    {
        QFile file(fileName);
        file.open(QIODevice::WriteOnly | QIODevice::Text);
        QTextStream out(&file);
        out << message;
        file.close();
    };
};

#endif

现在,我可以在主机上重用函数所需的次数。问题解决了!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66384153

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档