问题 QTimer只能用于以QThread启动的线程


所以我有一个有趣的问题....我正在尝试编写的程序崩溃了这个错误:

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示例的链接)都将非常感激。


9319
2017-09-16 20:29


起源

你在运行Qt事件循环吗? - Troubadour
@Troubadour,不 - CountMurphy


答案:


使用一个 QTimer 你需要有一个事件循环。 QNAM显然使用计时器来定期检查网络回复。

您需要启动应用程序事件循环 QCoreApplication::exec() 然后调用QNAM方法 post 之后。

我想你可以打电话 post 之前 exec 但你可能会遇到 这个bug

此外,请注意,Qt 4.7 QNAM最多不使用线程,但使用4.8 这是在改变


9
2017-09-16 22:25



这很有道理。就像我告诉Synthesisizerpatel一样,我不能在星期天之前测试这个。我应该假设QCoreApplication :: exec()应该通过我的程序main而不是Transmission类运行吗? - CountMurphy
是的,通常是最后一行 main 很简单 return app.exec()。 - Troubadour
到目前为止,错误没有出现,但我可以确认帖子正在工作!非常感谢Troubadour。如果我能多次提出你的答案,我会:) - CountMurphy
这回答了我的问题,略有不同。我试图在事件循环开始之前在main()中实例化的类构造函数中启动QTimer。 - Harvey
这也解决了我的问题,即QTest,一个单独的主要(通过qExec执行多个测试)和那些有定时器的测试。我添加了“QCoreApplication app(argc,argv)”,现在测试工作,没有错误被抛出。 - Deadolus


这可能与在Send方法中创建QNetworkAccessManager有关 - 请尝试使用RAII。

将Transmissions标头中的QNetworkAccessManager定义为类变量,并在ctor中创建一个类实例,然后您就可以从Send线程发布它。

否则我认为它超出了范围。


1
2017-09-16 20:38



我几天都无法测试这个,但是如果星期天有效,我会告诉你的。我不太明白如果networkManager在声明的方法中使用它会如何超出范围。你能解释一下吗? “你将能够从发送线程发布到它”我知道我的程序甚至不使用线程。 QNetworkAccessManager在某处创建了一个吗? - CountMurphy
QNAM的范围仅在'send'方法中 - 一旦该方法完成,该对象就消失了(除非你创建它的类变量/类实例。如果你创建它作为类变量并在其中创建一个实例ctor,然后它会在'send'运行后出现,并且能够响应/发送信号 java2s.com/Code/Cpp/Qt/DownloadfromURL.htm - synthesizerpatel
指针超出范围,而不是对象。该对象是Transmission实例的父级,因此在销毁时将被删除。 - Troubadour
正确,指针超出范围。我的解释不错,但解决方案仍然正确。 - synthesizerpatel
先生们,我感谢你们俩。该链接的+1 for synthesizerpatel也是如此。 - CountMurphy