windows - 为什么要尝试打开一个 TOpenDialog 产生大量线程?

标签 windows multithreading delphi topendialog

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

任何人都知道这是怎么回事?

最佳答案

想象一下,您想向您的 friend 展示太平洋西北部是多么美丽。您决定出发去拍几张照片 sunset over the Pacific .您真正关心的是返回到家的图像文件,在那里它们可以上传到 Facebook。实际上,相机、镜头和三脚架需要拖过 Olympics然后回来。您还需要带上将设置相机并按下快门的摄影师(您自己)。摄影师需要相对舒适地往返于那里,因此您需要坐下来让摄影师在旅途中休息。这个座位被封闭在一个 Shiny 的金属盒子里,盒子里有一堆其他金属、玻璃和橡胶部件,其中一些正在转动和往复运动。最后,大约两吨的东西(和一个活着的人)进行了数小时的旅行,燃烧了数加仑的碳氢化合物液体——目的是将一些信息从岸上转移到互联网上。

与您的应用程序完全相同。 当用户想要使用“打开文件”对话框打开文件时,用户希望能够:

  • 导航到包含文件的目录(该目录可能在本地硬盘驱动器或 CD/DVD/BR 或网络驱动器或存档等。媒体可能被加密或压缩,需要不同的显示。媒体可能不是插入,可能需要提示用户。媒体可能需要用户的凭据,必须询问);
  • 使用其 URI/UNC 连接到新目录(映射驱动器);
  • 在目录中搜索一些关键字;
  • 复制/删除/重命名一些文件;
  • 查看该目录中的文件列表;
  • 预览目录中每个文件的内容;
  • 选择要打开的文件;
  • 改变主意并决定不打开文件;
  • 做许多其他与文件相关的事情。

  • 操作系统通过本质上为您的进程提供大部分 Windows 资源管理器功能来让这一切发生。其中一些必须在后台发生,否则用户会提示“打开文件”对话框 react 迟钝。在后台运行某些任务的明显方法是在不同的线程上运行它们。所以这就是我们所看到的。

    你问留下的线程呢?好吧,其中一些保留在用户将决定打开另一个文件的情况下:在这种情况下,它可以节省大量时间、流量和输入。上次用于此特定过程的自定义身份验证? ——存储。那些讨厌的 PDF 的预览图标? - 还在那儿。目录中每部电影的长度和比特率? -- 仍然可用,无需重新解析它们。

    当然,这些线程并不仅仅是自己神奇地出现。查看有多少 DLL 已映射到进程中。看看其中的一些,可以对添加的功能有一个非常有趣的了解。

    另一种有趣的方式是在每个线程创建时转储调用堆栈。这显示了哪个 DLL(有时是哪个对象)创建了它们。 Here's x64 Win7 如何创建所有线程。可以发现 Explorer 框架的线程正在创建;一些 OLE 事件将用于实例化文件过滤器,其中一些可以生成预览图标、叠加和工具提示;属于搜索子系统的线程很少; shell 的设备枚举器(因此如果用户插入新设备,它将自动出现在打开的对话框中); shell 网络监视器(同上)和其他东西。

    好消息是它发生得很快,并且不会给您的流程增加太多开销。大多数线程大部分时间都在等待一些很少发生的事件(例如插入 USB key ),因此 CPU 不会花任何时间执行它们。每个线程在您的进程中消耗 1MB 的虚拟地址空间,但实际物理内存只有很少的 4Kb 页。大多数(如果不是全部)这些 DLL 都没有使用任何磁盘带宽来加载:它们已经在 RAM 中,因此它们几乎免费地映射到您的进程中。

    最后,用户在一个活泼的 UI 中获得了大量有用的功能,而这个过程只需要做很少的事情就可以实现所有这些。

    关于windows - 为什么要尝试打开一个 TOpenDialog 产生大量线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7373258/

    相关文章:

    delphi - ZDecompressStream() 导致内存泄漏

    c++ - CryptDecrypt 在解密字符串的末尾返回随机字符?

    python - 确定Python的实际内存使用情况

    c# - 当发出同步 I/O 调用时,当前线程 (C#) 的 ThreadState 是什么?

    java - 使用 JFrame 的图像幻灯片

    delphi - 当前时间值(in.Now())与 Julian Date To DateTime() 一起使用?

    excel - 用于 64 位 Visual Basic 的更新

    编译旧的c代码

    c++ - `decay_copy` 对象的构造函数中的 `std::thread` 有何作用?

    delphi - 在单元破坏调试信息中通用定义