我有一个非常简单的表单,上面有一个 TOpenDialog 和一个按钮。当我按下按钮时,它会在对话框中调用 Execute。如果我在调试器中观察,打开对话框的行为会产生 14 个线程,当我关闭对话框时它们也不会消失。
有人知道这是怎么回事吗?
我有一个非常简单的表单,上面有一个 TOpenDialog 和一个按钮。当我按下按钮时,它会在对话框中调用 Execute。如果我在调试器中观察,打开对话框的行为会产生 14 个线程,当我关闭对话框时它们也不会消失。
有人知道这是怎么回事吗?
想象一下,您想向您的朋友展示太平洋西北地区的美丽。你决定出发去拍几张太平洋上空的日落照片。您真正关心的是回家的图像文件,然后可以将它们上传到 Facebook。在现实中,相机、镜头和三脚架都需要拖过奥运会然后回来。您还需要带上负责设置相机并按下快门的摄影师(您自己)。摄影师需要在相对舒适的情况下移动到那里和回来,因此您可以坐在摄影师在旅行时休息的座位上。这个座位被封闭在一个闪亮的金属盒子里,里面有一堆其他的金属、玻璃和橡胶部件,其中一些部件正在转动和往复运动。最后,大约两吨的东西(和一个活人)进行了数小时的旅行,燃烧了加仑的碳氢化合物液体——目的是将一些信息从岸上转移到互联网上。
您的应用程序也会发生完全相同的事情。 当用户想要使用“打开文件”对话框打开文件时,用户希望能够:
操作系统通过本质上为您的进程提供大部分 Windows 资源管理器功能来让这一切发生。其中一些必须在后台发生,否则用户会抱怨“打开文件”对话框反应迟钝。在后台运行某些任务的明显方法是在不同的线程上运行它们。这就是我们所看到的。
你问留下的线怎么办?好吧,其中一些留在那里,以供用户决定打开另一个文件的情况下使用:在这种情况下,它可以节省大量时间、流量和打字。上次用于这一特定过程的自定义身份验证?——存储。那些讨厌的 PDF 的预览图标? - 还在那里。目录中每部电影的长度和比特率?-- 仍然可用,无需重新解析它们。
当然,这些线并不仅仅是神奇地自行出现。检查有多少 DLL 已映射到进程中。查看其中的一些,您可以非常有趣地了解添加了哪些功能。
另一种有趣的看待它的方法是在每个线程被创建的那一刻转储调用堆栈。这显示了哪个 DLL(有时是哪个对象)创建了它们。 以下是 x64 Win7 如何创建所有线程。可以发现 Explorer 框架的线程正在创建中;一些用于实例化文件过滤器的 OLE 活动,其中一些可以生成预览图标、覆盖和工具提示;属于搜索子系统的线程很少;shell 的设备枚举器(因此如果用户插入新设备,它将自动出现在打开的对话框中);shell 网络监视器(同上)和其他东西。
The good news is it happens fast and doesn't add too much overhead to your process. Most of the threads spend most of the time waiting for some seldom events (like USB key being plugged in), so the CPU doesn't spend any time executing them. Each thread consumes 1MB of virtual address space in your process, but only few 4Kb pages of actual physical memory. And most, if not all of those DLLs did not use any disk bandwidth to be loaded: they were already in RAM, so they just got mapped into your process for almost free.
In the end the user got a whole lot of useful functionality in a snappy UI, while the process had to do very little to achieve all that.