首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >QT应用冻结

QT应用冻结
EN

Stack Overflow用户
提问于 2019-06-22 05:42:12
回答 1查看 2.9K关注 0票数 1

我们开发了一个集摄像机和微控制器于一体的系统。GUI显示摄像机的图像和单片机的串行计数,使用串行线程轮询来自单片机的数据,并将信号发送给GUI显示,并使用一个单独的线程捕获图像并将其传递给主线程。应用程序的问题是,当系统处于空闲状态时,GUI冻结,我们必须重新启动应用程序才能开始工作(空闲意味着,用户不租赁任何按钮和计数,图像不断出现)。这里要注意的最重要的是GUI冻结问题在这里是不一致的。有几个系统安装,有些地方,冻结(没有响应)问题出现在2/3周和一些地方,每两天一次。等待应用程序响应是没有帮助的。

我的主要问题是,GUI冻结的主要原因是什么,以及是否有任何检查来实现串行线程和图像捕获线程,以避免不必要的数据泄漏。

EN

回答 1

Stack Overflow用户

发布于 2019-06-22 06:42:37

听起来,你正在经历一次并发冲突,这并不一定会导致崩溃,直到事情持续了足够长的时间,才能最终在正确的时间发生事件的神奇组合。

应用程序中有三个线程: GUI线程、串行线程和照相机线程。串行线程和摄像机线程从设备中收集数据,然后将它们传递给GUI线程以供显示。我认为串行线程和摄像头线程之间不共享任何数据,因此没有出现问题的风险。

如何将数据从串行线程和摄像机线程传递到GUI线程?这就是你可能有问题的地方。

大多数复杂的数据结构和Qt类都不是线程安全的,这意味着绝不能同时从两个或多个线程读取和写入它们。

以下是在线程之间安全传递数据的一些策略:

  1. 整数在CPU的指令集级别是原子的,因此您可以安全地从多个线程中读取和写入一个整数(或任何等于或小于一个整数的数据类型,例如bool、单个字符或指针),而不会出现任何不一致的状态。您必须用C++的std::atomic<>模板声明这些变量,以确保编译器不会执行破坏原子性的优化。 任何比整数更大/更复杂的线程,都会面临一个线程将其一半数据写入内存的风险,而另一个线程则同时读取该一半写入的数据,从而产生非常意外的结果,通常会导致应用程序崩溃或陷入无限循环。
  2. Qt中的信号和插槽是线程安全的。在线程之间传递复杂数据的一种方法是在一个线程中对数据进行emit,而在另一个线程中有一个slot接收该数据。在这种情况下,Qt会处理引擎盖下的任何并发问题。这里唯一的问题是,如果数据的使用者线程不能足够快地吸收数据,Qt的事件队列将塞满太多的数据,最终您的应用程序将崩溃,因为新的GUI事件(如鼠标单击、重新绘制事件等)不再能够通过阻塞的事件队列。
  3. 您可以使用QMutex来确保一次只读取或写入一个复杂的数据结构。QMutex允许您在一个或多个线程中阻止/停止执行,而单个线程“持有”互斥体并允许其执行,在数据上进行工作而不会有其他线程接触该数据的风险。当一个线程完成时,它会“释放”互斥体,然后允许另一个线程“持有”互斥体,继续执行,这样它就可以处理数据了。

就测试而言,通常情况下,您的应用程序因并发性违规而崩溃的几率越高,您的数据流率就越高。如果您能够人为地增加相机帧和“串行计数”传递到GUI线程的速率,您将能够更快地再现应用程序崩溃。一旦您成功地解决了并发问题,您应该能够用数据淹没系统,并且永远不会让它崩溃。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56712903

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档