QTimer 只能用于以 QThread 启动的线程
Posted
技术标签:
【中文标题】QTimer 只能用于以 QThread 启动的线程【英文标题】:QTimer can only be used with threads started with QThread 【发布时间】:2011-09-16 20:29:17 【问题描述】:所以我有一个有趣的问题....我正在(尝试)编写的程序因此错误而崩溃:
QObject::startTimer: QTimer can only be used with threads started with QThread
让我感到困惑的是我的程序是单线程的。有问题的课程的目标是将 POST 数据发送到我服务器上的 php 页面。一旦它尝试发送 POST,我就会收到该消息。这是我的代码。
#ifndef TRANSMISSIONS_H
#define TRANSMISSIONS_H
#include "name_spawn.h"
#include <QNetworkReply>
#include <QObject>
#include <QNetworkConfigurationManager>
class Transmissions : public QObject
Q_OBJECT
public:
Transmissions();
void Send(GeneratedData);
public slots:
void serviceRequestFinished(QNetworkReply*);
signals:
void configurationAdded(const QNetworkConfiguration);
void configurationChanged(const QNetworkConfiguration);
void configurationRemoved(const QNetworkConfiguration);
void onlineStateChanged(bool);
void updateCompleted();
;
#endif // TRANSMISSIONS_H
还有
#include "transmissions.h"
#include "name_spawn.h"
#include <QHttp>
#include <QUrl>
#include <QString>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <iostream>
#include <QNetworkAccessManager>
#include <QNetworkConfigurationManager>
#include <QObject>
using namespace std;
Transmissions::Transmissions()
void Transmissions::Send(GeneratedData User)
cerr<<"transmitting"<<endl;
QUrl serviceUrl = QUrl("http://192.168.1.138/postTest.php");
QByteArray postData;
QString username="user="+User.Email()+"&";
QString Passwd="password="+User.pass();
postData.append(username);
postData.append(Passwd);
QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(serviceRequestFinished(QNetworkReply*)));
networkManager->post(QNetworkRequest(serviceUrl), postData);
void Transmissions::serviceRequestFinished(QNetworkReply *reply)
//this will do other things once post is working
QString data = reply->readAll();
cerr <<"Data is "<< data.toStdString()<<endl;
我认为我正在尝试做的事情相当简单,但是让我无法让它发挥作用让我感到沮丧。我在文档中没有看到关于 QNetworkAccessManager 需要线程的任何内容。我承认我不太了解 Qt,因此非常感谢任何帮助(或完整 POST 示例的链接)。
【问题讨论】:
你在运行 Qt 事件循环吗? 【参考方案1】:要使用QTimer
,您需要有一个事件循环。 QNAM 显然使用计时器来定期检查网络回复。
您需要使用QCoreApplication::exec()
启动应用程序事件循环,然后调用QNAM 方法,如post
。
我认为您可以在exec
之前致电post
,但您可能会遇到this bug。
另外,请注意 Qt 4.7 QNAM 没有使用线程,而是使用了 4.8 this is changing。
【讨论】:
这很有意义。就像我告诉 synthesizerpatel 一样,我要到周日才能测试这个。我是否应该假设 QCoreApplication::exec() 应该通过我的程序 main 而不是在传输类中运行? 是的,通常main
的最后一行就是return app.exec()
。
到目前为止,该错误尚未出现,但我可以确认帖子正在运行!非常感谢游吟诗人。如果我能多次支持你的答案,我会:)
这回答了我的问题,但略有不同。在事件循环开始之前,我试图在我的 main() 中实例化的类构造函数中启动 QTimer。
这也解决了我使用 QTest、一个单独的 main(通过 qExec 执行多个测试)和那些具有计时器的测试的问题。我添加了“QCoreApplication app(argc,argv)”,现在测试工作正常,没有抛出任何错误。【参考方案2】:
这可能与在 Send 方法中创建 QNetworkAccessManager 有关 - 请尝试使用 RAII。
在Transmissions 的头文件中定义QNetworkAccessManager 作为类变量,并在ctor 中创建一个类实例,然后您就可以从Send 线程向它发布。
否则我认为它超出了范围。
【讨论】:
我将在几天内无法对此进行测试,但我会在周日之前通知您它是否有效。我不太明白如果 networkManager 以与声明它的方法相同的方法使用,它将如何超出范围。你能解释一下吗? “你将能够从发送线程向它发布”据我所知,我的程序甚至没有使用线程。 QNetworkAccessManager 是否在某处创建了一个? QNAM 的范围仅在“发送”方法内 - 一旦该方法完成,该对象就消失了(除非您创建它的类变量/类实例。如果您将其创建为class 变量并在 ctor 中创建一个实例,然后它会在 'send' 运行后出现,并且能够响应/发送信号。见java2s.com/Code/Cpp/Qt/DownloadfromURL.htm 指针超出范围,而不是对象。该对象是传输实例的父对象,因此在销毁时将被删除。 正确,指针超出范围。我的解释不好,但解决方案仍然正确。 先生们,谢谢你们。也为该链接的 synthesizerpatel +1。以上是关于QTimer 只能用于以 QThread 启动的线程的主要内容,如果未能解决你的问题,请参考以下文章
在 Windows 错误中使用 QProcess 启动进程:“计时器只能用于以 QThread 启动的线程”
Viber 程序停止工作日志文件:启动计时器计时器只能用于以 QThread 1 启动的线程