【发布时间】:2012-02-17 11:08:24
【问题描述】:
我正在开发一个相当大的应用程序,它负责进行实时运动跟踪和摄像机运动控制。它的任务是:
- 运动跟踪(由本机模块完成,该模块对来自网络摄像机的视频流进行解码,并通过回调将最大 1280x720 像素的图像缓冲区和跟踪结果提供给托管应用程序)
- 每秒大约 20 次从平移/倾斜硬件接收定位反馈数据并向其发送运动数据,以及从/向摄像机发送缩放命令
- 显示包括实时可视化在内的图像数据
- 图像和会话数据的编码和写入
- 视频的自动后处理由另一个进程完成
该应用程序使用 .NET 4.0 并具有 WPF 用户界面。
托管线程冻结
从一开始,我们就不得不面对冻结在 500 到 1500 毫秒之间的托管线程,这对于像这样的实时应用程序来说实在是太多了。
为了查明这些挂起何时发生,我创建了一个线程,其唯一任务是一直休眠 100 毫秒。然后我计算了睡眠真正花了多长时间,并准确地得到了相机停止移动的时间。它工作非常可靠,线程都同时挂起!
非托管线程不会冻结
虽然所有托管线程冻结非托管线程工作没有任何问题。我们通过独立于应用程序的托管部分编写的日志来检查这一点。
分析
我试图找出可能导致这种行为的现象:
- 当我们遇到这些问题时,整台机器会变慢:Windows 响应非常缓慢(例如,目录列表在 Windows 资源管理器和我的应用程序中都挂起半分钟,或者启动应用程序的时间非常长)
- 我们同时读取和写入数千个文件(跟踪和后处理应用程序),这可能会使窗口超负荷
- GUI 的响应变得非常缓慢
- 该应用程序使用大约 1.3GB 的虚拟内存(根据 Process.VirtualMemory64)/ 500MB 的工作集内存 (Process.WorkingSet64) - 是不是其中一些被交换到了硬盘上? (如何检查或解决?)
- 当然,如果我们终止进程,Windows 会再次快速响应,但 Windows 需要一段时间才能再次正常响应
非常感谢您提供有关如何调查此问题的提示。非常感谢!
【问题讨论】:
-
您所描述的听起来像是颠簸:en.wikipedia.org/wiki/Thrashing_%28computer_science%29 尝试使用 FileMon 和 DiskMon 来查看磁盘访问实际发生了什么。
-
运行 taskmgr.exe,进程选项卡。查看+选择列并勾选“页面错误增量”。通常的下一个结论是“啊,需要更多 RAM”。
-
@HansPassant:我在“页面错误增量”下得到的值最高为 70.000。这是否指向“颠簸”? (顺便说一句:您可以为这篇文章创建一个新答案而不是发表评论)
标签: c# .net multithreading