• 开启/实例化多个QThread,删除其中一个子线程,报错


    关注 码龄 粉丝数 原力等级 -- 被采纳 被点赞 采纳率 m0_61770108 2024-05-24 14:35 采纳率: 18.5% 浏览 2 首页/ 编程语言 / 开启/实例化多个QThread,删除其中一个子线程,报错 qtsqlite 开启/实例化多个QThread,删除其中一个子线程,报错源码: 报错: 收起 写回答 好问题 0 提建议 追加酬金 关注问题 微信扫一扫 点击复制链接 分享 邀请回答 编辑 收藏 删除 结题 收藏 举报 追加酬金 (90%的用户在追加酬金后获得了解决方案) 当前问题酬金 ¥ 0 (可追加 ¥500) ¥ 15¥ 20¥ 50¥ 100¥ 200 支付方式 扫码支付 二维码出错 点击刷新 支付金额 15 元 提供问题酬金的用户不参与问题酬金结算和分配 支付即为同意 《付费问题酬金结算规则》 结题 再想想 删除 再等等

    4条回答 默认 最新

    • 阿里嘎多学长 2024-05-24 14:36
      关注

      以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:


      根据您提供的源码截图和错误信息截图,我将尝试帮助您解决在Qt环境中启动多个QThread并在删除其中一个子线程时遇到的问题。

      首先,从源码截图中可以看到,您创建了一个ClientThread对象并将其移动到一个新的QThread中。接着,您通过信号和槽连接了QThreadClientThread对象,以及ClientThread和主界面之间的通信。最后,您启动了线程。

      在错误信息截图中,显示了一个访问违规(access violation)错误,具体是在QScopedPointerget()函数中。这通常意味着您尝试访问了一个空指针或者已经被释放的内存。

      以下是一些可能导致该问题的原因及相应的解决方案:

      1. 确保线程安全地结束

        • 在删除QThread对象之前,确保线程已经安全地结束。可以通过调用QThread::quit()QThread::wait()来确保线程结束。
      2. 避免重复删除

        • 检查是否有代码尝试多次删除同一个QThread对象。
      3. 检查QScopedPointer的使用

        • 错误信息指向QScopedPointerget()函数,这表明可能存在对空指针的访问。确保在使用QScopedPointer时,指针是有效的,并且在删除之前没有被释放。
      4. 检查信号和槽的连接

        • 确保所有信号和槽的连接都是正确的,并且在删除线程之前已经断开连接。
      5. 使用QThreadfinished信号

        • 通过连接QThread::finished信号到deleteLater()槽,可以确保在线程结束后自动删除线程对象。
      6. 检查数据库操作

        • 由于您的项目中涉及到SQLite数据库操作,确保数据库操作在正确的线程中执行,并且数据库连接在线程结束前正确关闭。
      7. 调试和日志记录

        • 使用Qt Creator的调试工具来逐步跟踪代码,查看在删除线程之前发生了什么。
        • 在关键代码段添加日志记录,以帮助诊断问题。

      如果您需要进一步的帮助,建议提供更多的代码上下文,特别是与QScopedPointer相关的部分,以及任何可能与线程结束相关的代码。这将有助于更准确地诊断问题所在。

      请注意,由于我没有访问互联网,因此无法提供外部链接。上述建议基于您提供的信息和Qt编程的一般实践。

      展开全部

      评论 编辑记录
    • 专家-赤兔[在线] 全栈领域优质创作者 2024-05-24 14:36
      关注

      引自免费微信小程序:皆我百晓生

      从错误信息来看,你在尝试访问一个已经释放的对象指针,这通常是因为在QThread对象被删除后,还在尝试与其交互。在Qt中,你应该避免直接管理QThread对象的生命周期,而是让其关联的槽函数或者工作线程中的任务在完成后自动结束线程。

      为了避免这个问题,你可以通过以下步骤进行修复:

      1. 使用信号和槽来控制线程的启动和停止。
      2. 不要手动删除QThread对象,而是在槽函数中调用QThread::quit()QThread::wait()方法来优雅地关闭线程。

      这里是修改后的代码示例:

      首先,在头文件中添加信号声明:

      signals:
          void stopThread();
      

      然后,在你需要创建线程的地方,例如构造函数或初始化部分,创建并连接信号:

      // 假设你有一个名为MyWorker的类,它继承于QObject
      MyWorker *worker = new MyWorker(this);
      QThread *thread = new QThread;
      worker->moveToThread(thread);
      
      connect(thread, &QThread::started, worker, &MyWorker::startWork);
      connect(worker, &MyWorker::workFinished, thread, &QThread::quit);
      connect(worker, &MyWorker::workFinished, worker, &QObject::deleteLater);
      connect(this, &YourClass::stopThread, thread, &QThread::quit);
      thread->start();
      

      在这个例子中,当stopThread信号发出时,会触发QThread::quit(),从而终止线程的工作。当线程完成所有工作后,它会自动调用QObject::deleteLater()删除自身,这样就避免了手动删除线程可能导致的问题。

      对于你的具体代码,你可能需要找到触发on_pushButton_disconnect_DB_clicked这个槽函数的地方,并在其中发送stopThread信号:

      void Client::on_pushButton_disconnect_DB_clicked()
      {
          emit stopThread();
      }
      

      确保你的类实现了上述的信号和槽,以及在合适的位置发射这些信号。这样应该可以解决你在删除子线程时遇到的问题。如果你还有其他疑问或遇到新问题,欢迎继续提问。

      展开全部

      评论 编辑记录
    • Kwan的解忧杂货铺 2024-05-24 14:36
      关注

      下午好🌅🌅🌅
      本答案参考ChatGPT-3.5

      根据提供的信息,错误发生在删除一个子线程时,可能出现了读取违规的访问。具体可以在调试器中观察发生错误的地方。可能的解决方案如下:

      1. 确认子线程是否正确被销毁,在子线程结束时需要调用deleteLater(),在主线程中调用quit()wait()

      2. 确认线程中是否有共享资源,如果有需要进行线程安全的保护。

      3. 确认在主线程中是否维护着子线程对象指针的列表,如果有,删除子线程时需要从列表中移除。

      4. 问题可能出在子线程删除后,在主线程中尝试使用已被删除的子线程指针,可以考虑在删除后,清空指针。

      以上解决方案可以按照以下步骤尝试修改代码:

      1. ClientThread 的头文件中定义一个删除信号和槽,用来告知主线程子线程已经结束:
      signals:
          void finished(ClientThread *thread);
      
      1. 通过连接上述删除信号和槽,在子线程结束时调用 deleteLater()quit()wait();在主线程中移除子线程对象指针。
      void on_pushButton_connect_Thread_clicked() {
          QThread* thread = new QThread();
          ClientThread* clientThread = new ClientThread(lock);
          connect(thread, &QThread::finished, clientThread, &QObject::deleteLater);
          connect(clientThread, &ClientThread::finished, this, [=](ClientThread* thread) {
              m_threads.removeOne(thread);
              thread->quit();
              thread->wait();
          });
          clientThread->moveToThread(thread);
          connect(this, &Client::printf, clientThread, &ClientThread::printf);
          connect(this, &Client::openDB, clientThread, &ClientThread::openDB);
          ...
          m_threads.append(clientThread);
          thread->start();
      }
      
      1. 在主线程中,在指向已删除的子线程对象的指针后面添加清空指针的语句。
      void on_pushButton_disconnect_DB_clicked() {
          QMapIterator i(m_mapTable);
          while (i.hasNext()) {
              i.next();
              delete i.value();
          }
          m_mapTable.clear();
          Q_FOREACH (ClientThread* clientThread, m_threads) {
              clientThread->disconnect();
          }
          m_threads.clear();
          ui->label_DB_status->setText("DISCONNECTED");
          ui->label_DB_status->setStyleSheet("QLabel{color:red}");
          thread->quit();
          thread->wait();
          thread = nullptr;
      }
      

      注意:以上代码仅供参考,具体解决方案还需根据实际情况修改。

      展开全部

      评论
    • 专家-百锦再@新空间代码工作室 全栈领域优质创作者 2024-05-24 14:38
      关注

      import sysfrom PyQt5.QtCore import QThread 
      class MyThread(QThread):def run(self):print("
      Thread running"
      )threads = []for i in range(5):thread = MyThread()threads.append(thread)thread.start()
      del threads[0]
      sys.exit()

      报错信息:

      QObject: Cannot create children for a parent that is in a different thread.(Parent is QThread(0x7fffc3600990), parent's thread is QThread(0x7fffc36015b0), current thread is QThread(0x7fffc364f100)

      有问题你别着急,评论留言都可以,看到马上就回复,尽量及时补充齐
      评论
    编辑
    预览

    报告相同问题?

  • 相关阅读:
    河北地质大学计算机考研资料汇总
    人工神经网络与遗传算法,神经网络和算法的关系
    娄底医药工业洁净厂建设基本要点概述
    Django render()函数页面渲染
    java计算机毕业设计医院出入院管理系统源程序+mysql+系统+lw文档+远程调试
    docker简易入门(极简,纯干货)
    //按层遍历二叉树,并收集结点
    ARM的异常处理
    通配符匹配
    shared_ptr 和 make_shared 的使用
  • 原文地址:https://ask.csdn.net/questions/8108688