Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当从2个线程发出2个网络请求时,Qt应用程序崩溃_Qt_Networking_Qthread_Qnetworkaccessmanager - Fatal编程技术网

当从2个线程发出2个网络请求时,Qt应用程序崩溃

当从2个线程发出2个网络请求时,Qt应用程序崩溃,qt,networking,qthread,qnetworkaccessmanager,Qt,Networking,Qthread,Qnetworkaccessmanager,我有一个Qt应用程序,它在启动时从主线程启动两个线程。这两个线程都使用QNetworkAccessManager对象的不同实例发出网络请求。我的程序有50%的时候会崩溃,我不确定哪个线程会崩溃 两个线程之间没有直接发生的数据共享或信令。当某个事件发生时,其中一个线程向主线程发出信号,而主线程又可能向第二个线程发出信号。然而,通过打印日志,我非常确定在发送信号期间不会发生崩溃 两个线程的结构如下所示。除了URL等,线程之间几乎没有任何区别 MyThread() : QThread() {

我有一个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在某种程度上是罪魁祸首

我对撞车的原因一无所知。如果有任何建议或建议,我将不胜感激。提前感谢。

首先!首先修复线程

//编辑 根据我自己对这种模式的经验,我知道它可能会导致许多不明确的崩溃。我会从清理这件事开始,因为它可能会理顺一些事情,让发现问题变得清晰。我也不知道如何调用
makeRequest
。还有关于QNetworkRequest。它只是一个数据结构,所以您不需要将它放在堆上。堆栈构造就足够了。此外,您还应该记住(或以某种方式保护)不要覆盖m_回复指针。您是否多次调用
makeRequest
?如果这样做,则可能会导致在上一个请求完成后删除当前处理的请求

如果调用makeRequest两次会发生什么情况:

  • makeRequest的第一个调用分配m_应答指针
  • makeRequest的第二次调用第二次分配m_应答指针(替换分配的指针,但不删除指向的对象)
  • 第二个请求在第一个请求之前完成,因此调用processReply。deleteLater以秒为单位排队
  • 在eventloop的某个地方,第二个回复被删除,所以从现在起,m_回复指针指向一些随机(删除的)内存
  • 第一个应答完成,因此调用另一个processReply,但它在指向垃圾的m_reply上运行,因此每次调用m_reply都会产生崩溃
  • 这是一种可能的情况。这就是为什么你不会每次都崩溃


    我不确定为什么在回复完成时调用出口(0)。如果您使用多个makeRequest调用,则此处也不正确。请记住,QThread是单个线程的接口,而不是线程池。所以,当线程实例仍在运行时,不能再次调用它。另外,如果要在入口点
    run()
    中创建网络访问管理器,则应在
    exec()
    之后的相同位置将其删除。请记住,
    exec()
    是阻塞的,因此在线程退出之前不会删除对象。

    在应用程序开发的后期,我确实遇到了这两篇文章(错误的方法和正确的方法)。我的Java背景也帮不上忙,您通常通过扩展线程来执行线程。无论如何,问题似乎在于网络访问管理器本身,而不是线程。我将使用一个简单的代码片段来尝试给定的方法,该代码片段再现了这个问题。请提供您对QNetworkAccessManager的任何细微差别的意见。谢谢