【发布时间】:2019-04-20 20:16:30
【问题描述】:
我有一个对网络执行请求并解析数据的类。如何正确实现它的请求中止?
想象一下我有这样一门课:
class MyClass
{
public:
...
void doRequest()
{
m_reply = m_manager.get(...);
QEventLoop waitForResponse;
connect(m_reply, &QNetworkReply::finished, &waitForResponse, &QEventLoop::quit);
waitForResponse.exec();
// Check if request was aborted (otherwise, application will crash)
if (m_reply == nullptr)
return;
// Check for network errors, write result to m_data and delete m_reply;
...
}
void abort()
{
if (m_reply != nullptr)
m_reply->abort();
}
QString data()
{
return m_data;
}
...
private:
QNetworkAccessManager *m_manager;
QPiinter<QNetworkReply> m_reply;
QString m_data;
}
这是一个按下按钮的例子:
class MainWindow : public QMainWindow
{
...
private slots:
MainWindow::on_myButton_pressed()
{
m_myClass->abort();
m_myClass->doRequest();
ui->myTextEdit->setText(m_myClass->data());
}
private:
MyClass m_myClass;
}
当你按下按钮时,如果之前的请求没有完成,那么它就会被取消。这行得通。但在这种情况下,新请求将数据写入QTextEdit 并退出函数,然后旧请求从它自己的循环返回并再次将相同的m_data 写入QTextEdit。
正确吗?也许有更正确的方法来实现这一点?
【问题讨论】:
-
等一下...抱歉,没听清楚:您是否将
QTextEdit文本设置了两次?但为什么?你不能在设置m_data之前检查m_reply是否被中止吗? -
@MasterAler,是的,我有两次
setText。我有error()方法,它返回doRequest()中发生的错误枚举。我可以在取消后设置错误,它会起作用,但它看起来很奇怪......在这种情况下,我将拥有带有有效数据的 MyClass 和来自error()的Error::Aborted。这看起来不是很清楚,至于我…… -
作为一个类设计问题,这看起来不太清楚,这是真的。我会使用
QtConcurrent::run+QFuture之类的东西而不是事件循环,这样一键点击 == 一项任务。但是使用当前代码,您也可以在成功请求后重置错误状态(甚至使用您自己的枚举),以便在任意时刻存在一对有效且符合要求的数据和错误状态。 -
不幸的是,由于
QEventLoop,被取消的旧请求比成功的请求执行得晚。因此,我将有一个有效的m_data(使用新查询生成)和error(),它从旧查询返回错误。还有我的问题。想过QtConcurrent,但是不知道怎么和QNetworkReply集成,已经是异步的了。 -
那么它看起来像一个设计缺陷。您有一个按钮,它发送 多个 独立请求,但它们由具有一个共同状态的 一个 类实例处理。不好。可能有不同的解决方案,但一般来说,每个请求可能应该有一个 MyClass 实例。顺便说一句,在异步调用中使用异步类似乎没有问题,afaik。
标签: c++ qt networking