QProcess:进程仍在运行时被销毁

时间:2013-02-21 05:30:47

标签: c++ c multithreading qt4 multiprocess

我正在使用Qt为xmgrace(2D绘图库)开发自定义控件界面。 我的项目中有3个组件:

  1. 用Qt制作的GUI
  2. 一个QThread,它在后台线程中运行C中的一些共享对象代码。
  3. 使用管道连接到上述两者的xmgrace窗口。 (使用grace_np库)
  4. 来自(1) --> (2)的通信是通过更改共享对象代码中声明的某些全局变量的状态来完成的。

    来自(1) --> (3)&的通讯(2) --> (3)使用grace_np库提供的内置函数。

    现在,来自(2) --> (1)的通信正是造成问题的原因。我尝试了两种可能的方法: a)在Qt代码中声明共享对象,该代码发出Qt信号并在C代码中调用。 b)从线程返回并使用返回值执行某些操作,然后重新启动线程。

    这两种方法都给出了不可靠的结果。我的GUI卡住/导致分段错误,我收到消息:

    QProcess: Destroyed while process is still running

    我没有在我的代码中的任何地方使用QProcess类。所以这已成为一个谜。 请提供一些有关可能原因的信息。

    PS:(3)的管道是单向的,只需要这种方式。

    修改1:

    仅供参考我正在使用Qt 4.2,所以我不能使用QObject方法然后使用movetothread() 我很抱歉没有提供代码,因为我不能因为公司政策,也因为我不知道该放什么(它太大了)。共享的c代码是400k +行

    我相信我找到了问题的罪魁祸首。似乎使用类QMessageBox导致了这个问题。我最初使用的是QMessageBox的静态函数。现在我已经尝试在堆栈和堆上声明它,但问题仍然存在。 但我发现从我的代码中删除对QMessageBox的所有调用都解决了这个问题。 但现在的问题是,如何显示消息? 我只是在这里推测,但是QMessageBox的模态性质是否可能阻止我的程序和xmgrace之间存在的管道并随后导致它退出?然后创建自定义QMessageBox(非模态)可能会解决此问题。

    编辑2:

    我没有从工作线程调用QMessageBox。再加上我使用工作线程的方式,除非我关闭程序,否则它永远不会返回。为了说明我的QThread :: run函数的形式如下:

    QThread_Object::run()
    {
      c_init();
      c_main();
    }
    

    其中c_init& c_run是从共享c代码链接的函数。因此不可能直接在这些内部调用QMessageBox。 现在我打算取消QMessageBox并使用QMainWindow状态栏。但是它并没有提供整个功能。我想这可能是Qt 4.2中的一个错误

    编辑3:

    我之前提到(2) --> (1)的通讯是造成问题的原因。现在我完全废除了这种通信,并且更准确地发现问题是由启动工作线程后随时调用QMessageBox引起的。早些时候上面提到的通信导致Qt间接发出信号并调用QMessageBox,我认为这是罪魁祸首。

    编辑4:

    好吧,我从一开始就忘了提到这个问题最大的谜团。我基本上通过ssh工作(放置A)在工作站(地方B)上我编码并运行该程序。 B连接在2个物理网络上。 A通过网络1连接到B.现在,当我在A的终端(即通过网络1在ssh上)工作时,此问题从不发生。但是当我直接访问B或通过网络2通过ssh访问B时,它会一直发生。请注意,每次只在B上执行代码。这些网络都被狩猎者使用。

    编辑5

    最后,我通过对QDialog进行子类化并制作自定义MessageBox来解决我的问题,因为我并不真正需要QMessageBox的扩展功能。我仍然不知道QMessageBox内究竟是什么导致了这个问题。我想Qt中的一些错误将永远是个谜。

1 个答案:

答案 0 :(得分:1)

由于没有代码我在黑暗中稍微拍摄,但听起来你的QProcess是在堆栈上创建的,无论是有意还是无意,或者你的QThread过早被破坏了。我会把钱放在你的QThread对象上错误地启动。很难责怪你,因为文档是(或直到最近)搞砸了。考虑阅读this threadthis thread,并且根本不要对QThread进行子类化。

修改 如果QMessageBox是你的罪魁祸首,那么我猜你正在从子线程中显示它。来自documentation

  

在GUI应用程序中,主线程也称为GUI线程   因为它是唯一允许执行GUI相关的线程   操作

有几种方法可以显示来自子线程的消息。就个人而言,我使用qt的错误报告方案并将qCritical,qDebug等重定向到stderr。另一种更简单的方法是让你emit来自你的工作线程的QString信号被你的GUI线程捕获,然后显示/收集错误。我喜欢让我的MainWindow收集错误,然后在工作线程结束时立即显示它们。

编辑2: 由于问题似乎是QMessageBox是模态的(即,当工作线程向前移动时阻塞主线程),您可以通过在非模态模式下使用QMessageBox轻松解决此问题。只需将0作为QMessageBox构造函数/静态函数中的父窗口小部件传递。处理将继续而不等待用户退出窗口 - 这也可能导致同时打开多个消息框。如果这有助于避免错误,请仔细检查您的代码,以确保在关闭后正确销毁窗口。