我正在使用Qt4编写应用程序。
我需要从给定的http地址下载一个非常短的文本文件。
文件很短,我的应用程序需要能够继续,所以我想确保下载是阻止的(如果文件未找到/不可用,则会在几秒钟后超时)。< / p>
我想使用QHttp :: get(),但这是一种非阻塞方法。
我以为我可以使用一个帖子:我的应用程序会启动它,并等待它完成。线程将处理下载并在下载文件或超时后退出。
但我不能让它发挥作用:
class JSHttpGetterThread : public QThread
{
Q_OBJECT
public:
JSHttpGetterThread(QObject* pParent = NULL);
~JSHttpGetterThread();
virtual void run()
{
m_pHttp = new QHttp(this);
connect(m_pHttp, SIGNAL(requestFinished(int, bool)), this, SLOT(onRequestFinished(int, bool)));
m_pHttp->setHost("127.0.0.1");
m_pHttp->get("Foo.txt", &m_GetBuffer);
exec();
}
const QString& getDownloadedFileContent() const
{
return m_DownloadedFileContent;
}
private:
QHttp* m_pHttp;
QBuffer m_GetBuffer;
QString m_DownloadedFileContent;
private slots:
void onRequestFinished(int Id, bool Error)
{
m_DownloadedFileContent = "";
m_DownloadedFileContent.append(m_GetBuffer.buffer());
}
};
在创建线程以启动下载的方法中,以下是我正在做的事情:
JSHttpGetterThread* pGetter = new JSHttpGetterThread(this);
pGetter->start();
pGetter->wait();
但这不起作用,我的应用程序一直在等待。它看起来很亮,从来没有调用过'onRequestFinished'。
有什么想法吗?
有没有更好的方法来做我想做的事情?
答案 0 :(得分:5)
有点晚了但是: 不要使用这些等待循环,正确的方法是使用来自QHttp的done()信号。
来自我所看到的requestFinished信号仅适用于您的应用程序完成请求的时间,数据可能仍然在下降。
您不需要新线程,只需设置qhttp:
httpGetFile= new QHttp();
connect(httpGetFile, SIGNAL(done(bool)), this, SLOT(processHttpGetFile(bool)));
另外不要忘记刷新processHttpGetFile中的文件,因为它可能不在磁盘上。
答案 1 :(得分:4)
您可以直接进入调用processEvents
:
while (notFinished) {
qApp->processEvents(QEventLoop::WaitForMore | QEventLoop::ExcludeUserInput);
}
其中notFinished
是可以从onRequestFinished
广告位设置的标志。
ExcludeUserInput
将确保在等待时忽略GUI相关事件。
答案 2 :(得分:3)
如果你完成了,你必须致电QThread::quit()
或exit()
- 否则你的线程将永远运行......
答案 3 :(得分:1)
我选择实施David的解决方案,这似乎是最简单的。
但是,我还处理了一些事情:
结果为(或多或少)伪代码:
class BlockingDownloader : public QObject
{
Q_OBJECT
public:
BlockingDownloaderBlockingDownloader()
{
m_pHttp = new QHttp(this);
connect(m_pHttp, SIGNAL(requestFinished(int, bool)), this, SLOT(onRequestFinished(int, bool)));
}
~BlockingDownloader()
{
delete m_pHttp;
}
QString getFileContent()
{
m_pHttp->setHost("www.xxx.com");
m_DownloadId = m_pHttp->get("/myfile.txt", &m_GetBuffer);
QTimer::singleShot(m_TimeOutTime, this, SLOT(onTimeOut()));
while (!m_FileIsDownloaded)
{
qApp->processEvents(QEventLoop::WaitForMoreEvents | QEventLoop::ExcludeUserInputEvents);
}
return m_DownloadedFileContent;
}
private slots:
void BlockingDownloader::onRequestFinished(int Id, bool Error)
{
if (Id == m_DownloadId)
{
m_DownloadedFileContent = "";
m_DownloadedFileContent.append(m_GetBuffer.buffer());
m_FileIsDownloaded = true;
}
}
void BlockingDownloader::onTimeOut()
{
m_FileIsDownloaded = true;
}
private:
QHttp* m_pHttp;
bool m_FileIsDownloaded;
QBuffer m_GetBuffer;
QString m_DownloadedFileContent;
int m_DownloadId;
};
答案 4 :(得分:0)
我使用QNetworkAccsessManager来满足同样的需要。因为这个类管理连接RFC基础(6个进程同时)和非阻塞。
答案 5 :(得分:-1)
给GUI一些时间等待线程然后放弃。
类似的东西:
JSHttpGetterThread* pGetter = new JSHttpGetterThread(this);
pGetter->start();
pGetter->wait(10000); //give the thread 10 seconds to download
或者...
为什么GUI线程必须等待“下载线程”?当应用程序启动时创建下载程序线程,将finished()信号连接到其他对象,启动下载程序线程,然后返回。当线程完成后,它将发出另一个可以恢复进程的对象的信号。