尝试打开TOpenDialog为什么会产生大量线程?

16

我有一个非常简单的表单,上面有一个TOpenDialog和一个按钮。当我按下按钮时,它会调用对话框上的Execute方法。如果我在调试器中观察,打开对话框的行为会产生大约14个线程,而且当我关闭对话框时,这些线程并不消失。

有人知道这是怎么回事吗?


3
只有14秒?感觉整个操作系统都在启动...就我个人而言,我从来没有明白为什么需要这么久才能显示一个文件对话框。 - Andreas Rejbrand
1
并且加1,因为你让我学到了新东西。这个显著的延迟在通过调试器运行应用程序时出现。 - Andreas Rejbrand
14
我记得读过一篇文章,说通用文件对话框最终会加载所有的Shell扩展,因此这些DLL可能会做出各种不可预测的操作。 - Luke
@Mason:我猜你根本不需要担心它们。毕竟,微软和Embarcadero都不是傻瓜...而且,正如我刚刚了解到的那样,可怕的延迟只会在通过调试器运行程序时出现。你有什么特别的原因让这成为一个问题吗? - Andreas Rejbrand
嗯...我得到了23个新线程。而且我很少安装东西。 - Andreas Rejbrand
显示剩余14条评论
1个回答

8
想象一下,你想向朋友展示太平洋西北地区的美丽。你决定出发旅行,拍摄几张太平洋上的日落照片。你真正关心的是图像文件能顺利传回家中,然后上传到Facebook。实际上,相机、镜头和三脚架需要搬过奥林匹克山脉来回。你还需要带上摄影师(你自己),他将设置相机并按下快门。摄影师需要以相对舒适的方式移动,因此你坐在一个座位上,摄影师在旅途中休息。这个座位被封装在一个闪亮的金属盒子里,里面有许多其他的金属、玻璃和橡胶部件,其中一些正在旋转和往复运动。最终,约两吨的东西(和一个活生生的人)花费数小时的时间旅行,燃烧着加仑的碳氢化合物液体——目的是将一些信息从海岸传输到互联网上。

你的应用程序也会发生完全相同的事情。 当用户想要使用“打开文件”对话框打开文件时,用户希望能够:

  • 导航到包含文件的目录(该目录可能位于本地硬盘、CD / DVD / BR或网络驱动器或存档等位置。介质可能已加密或压缩,需要以不同方式显示。介质可能未插入,因此可能需要提示用户。介质可能需要用户的凭据,必须询问);
  • 使用其URI / UNC连接到新目录(映射驱动器);
  • 搜索目录中的某些关键字;
  • 复制/删除/重命名某些文件;
  • 查看该目录中的文件列表;
  • 预览目录中每个文件的内容;
  • 选择要打开的文件;
  • 改变他/她的想法并决定不打开文件;
  • 执行许多其他与文件相关的操作。
操作系统通过为进程提供大部分Windows资源管理器功能,来实现所有这些。一些操作必须在后台进行,否则用户会抱怨打开文件对话框的响应速度过慢。在后台运行某些任务的明显方法是在不同的线程上运行它们。所以我们看到了这个。

你问剩下的线程怎么办?嗯,一些线程留在那里是为了万一用户决定打开另一个文件:这样可以节省大量时间、流量和输入。用于上次特定进程的自定义身份验证信息?——已存储。那些讨厌的PDF预览图标?——还在。目录中每个电影的长度和比特率?——仍然可用,无需重新解析。

当然,这些线程并不是自己神奇地出现的。查看有多少DLL被映射到该进程中。从其中一些中可以得到相当有趣的功能添加图片。

另一种有趣的观察方式是在每个线程创建时转储调用堆栈。这显示了创建它们的DLL(有时还包括对象)。这是x64 Win7创建所有线程的方法。可以找到创建资源管理器框架线程的活动;一些OLE活动将用于实例化文件过滤器,其中一些可以生成预览图标、覆盖和工具提示;属于搜索子系统的几个线程;shell设备枚举器(因此如果用户插入新设备,它将自动出现在打开对话框中);shell网络监视器(同上)以及其他内容。
好消息是它发生得很快,不会给您的进程增加太多开销。大多数线程大部分时间都在等待一些很少见的事件(比如插入USB键),所以CPU不会花费任何时间执行它们。每个线程在您的进程中消耗1MB的虚拟地址空间,但只占用了几个4KB的实际物理内存页。而且大多数DLL(如果不是全部)没有使用任何磁盘带宽进行加载:它们已经在RAM中了,因此它们只是免费映射到您的进程中。
最终用户在一个快速的UI中获得了许多有用的功能,而整个过程只需要做很少的工作就可以实现所有这些。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接