我有一个Qt应用程序,它在启动时从主线程启动两个线程。这两个线程都使用QNetworkAccessManager对象的不同实例发出网络请求。我的程序在大约50%的时间内都会崩溃,我不确定哪个线程崩溃了。
两个线程之间没有直接发生数据共享或信令。当某个事件发生时,一个线程向主线程发出信号,主线程又可以发出第二个线程的信号。但是,通过打印日志,我很确定在信令过程中不会发生崩溃。
两个线程的结构如下。除了URL等之外,线程之间几乎没有任何区别。
MyThread() : QThread() {
moveToThread(this);
}
MyThread()::~MyThread() {
delete m_manager;
delete m_request;
}
MyThread::run() {
m_manager = new QNetworkAccessManager();
m_request = new QNetworkRequest(QUrl("..."));
makeRequest();
exec();
}
MyThread::makeRequest() {
m_reply = m_manager->get(*m_request);
connect(m_reply, SIGNAL(finished()), this, SLOT(processReply()));
// my log line
}
MyThread::processReply() {
if (!m_reply->error()) {
QString data = QString(m_reply->readAll());
emit signalToMainThread(data);
}
m_reply->deleteLater();
exit(0);
}
现在奇怪的是,如果我没有启动其中一个线程,程序运行正常,或者至少在大约20次调用中不会崩溃。如果两个线程一个接一个地运行,程序不会崩溃。如果我同时启动和运行两个线程,程序只会在 一半 时崩溃。
我从日志中收集的另一个有趣的事情是,每当程序崩溃时,标记为my log line
的行是两个线程都要执行的最后一行。所以我不知道哪个线程导致崩溃。但它让我怀疑QNetworkAccessManager在某种程度上应该受到指责。
我对导致崩溃的原因一无所知。我将不胜感激任何建议或指示。提前谢谢。
答案 0 :(得分:0)
首先you're doing it wrong!首先修复线程
//编辑
根据我自己对这种模式的经验,我知道它可能导致许多不清楚的崩溃。我会从清除这个东西开始,因为它可能会使一些事情变得清晰,并使发现问题变得清晰。另外我不知道你如何调用makeRequest
。还有关于QNetworkRequest。它只是一个数据结构,因此您不需要在堆上创建它。堆栈结构就足够了。你也应该记住(或以某种方式保护)覆盖m_reply指针。你不止一次打电话给makeRequest
吗?如果这样做,则可能导致在上一个请求完成后删除当前处理的请求。
如果你两次调用makeRequest会发生什么:
这是可能的情景之一。这就是你每次都不会崩溃的原因。
我不确定你为什么在回复结束时调用exit(0)。如果你使用多次makeRequest调用,这里也是不正确的。请记住,QThread是单个线程的接口,而不是线程池。因此,当线程实例仍在运行时,您无法在线程实例上第二次调用start()
。此外,如果您要在入口点run()
中创建网络访问管理器,则应在exec()
后的同一位置删除它。请记住,exec()
正在阻止,因此在线程退出之前不会删除对象。