1

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

  1. 用 Qt 制作的 GUI
  2. 一个 QThread,它在后台线程中从 C 运行一些共享对象代码。
  3. 使用管道连接到上述两者的 xmgrace 窗口。(使用 Grace_np 库)

(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 在工作站(位置 B)上工作(位置 A),我在该工作站上编写代码并运行该程序。B 连接在 2 个物理网络上。A 通过网络 1 连接到 B。现在,从我在 A 的终端(即通过网络 1 在 ssh 上)工作时,这个问题从未发生过。但是当我直接访问 B 或通过网络 2 通过 ssh 访问 B 时,它始终会发生。请注意,每次代码仅在 B 上执行。这两个网络都被数百人使用。

编辑 5

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

4

1 回答 1

1

由于没有代码我在这里有点暗中拍摄,但听起来你的 QProcess 是有意或无意地在堆栈上创建的,或者你的 QThread 过早地被破坏了。我会把钱花在你的 QThread 对象被错误地启动上。很难怪你,因为文档是(或直到最近)搞砸了。考虑阅读这个线程这个线程,并且根本不要子类 QThread。

编辑: 如果 QMessageBox 是你的罪魁祸首,那么我猜你是从子线程中显示它的。从文档中:

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

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

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

于 2013-02-21T17:32:38.403 回答