3

Shell 命名空间扩展相当复杂。在过去的 10 年里,我们一直在构建一个 shell 命名空间扩展;最新的版本是 MagicRAR (www.magicrar.com) 中的存档文件夹功能。

不幸的是,尽管编码非常仔细,确保线程正确访问共享内存等,我们的 shell 命名空间扩展仍然偶尔会崩溃。Explorer 主机进程在使用我们的 shell 命名空间扩展期间或之外崩溃。

我们使用了多种工具,例如 AQTime Pro 来解决我们的 shell 命名空间扩展代码。没有报告内存覆盖或其他类似的访问问题。只剩下一个罪魁祸首:VCL 不是线程安全的!

事实上,我们正在使用 VCL 作为我们的 shell 命名空间扩展的一部分;Explorer 中的文件列表实际上是一个托管控件,在我们自己的 shell 命名空间扩展的情况下,它实际上是一个 VCL 窗口。我们现在甚至想知道(经过多代开发)这是否是一个允许的场景......

主应用程序对象甚至不存在于我们的 shell 命名空间扩展 DLL 中。使用 TThread.Synchronize 死锁资源管理器,因为尚未在任何地方创建主 VCL 线程。我们是否需要手动创建一个主 VCL 线程(如何?) - 可能在另一个 DLL 中 - 并通过该 DLL 重新路由我们所有的 UI 创建/更新/破坏?

请记住,资源管理器可能会显示任意数量的包含我们的 VCL 窗口的窗口。根据目标系统的配置,Explorer 也可以作为多个独立进程或单个进程运行。

我们的 shell 命名空间扩展基于 John Lam 的起点(正如大多数 Delphi shell 命名空间开发人员所知道的那样)。当然,正如您在最终产品中看到的那样,对这个起点进行了重大修改。John Lam 甚至从未在他的幻灯片和示例项目中讨论过 VCL 线程不安全的问题。

在过去十年中,我们还尝试使用多个版本的 ShellPlus 组件。他们已经完成了一些出色的工作,但不幸的是,根据我们的经验,即使是基于他们的代码的非常初级的工作也提供了比我们自己的代码更糟糕的结果。

ShellPlus 实际上还提供了使用 Explorer 自己的预定义主机窗口的功能,而不是创建自定义 VCL 窗口;虽然这可能会回避任何 VCL 线程问题,但根据我们的经验,即使这也不是一个可行的解决方案 - 因为 ShellPlus shell 命名空间扩展始终不如我们自制的代码稳定,无论 VCL 是否窗口化。

所以首先;这个问题是一个理论上的问题 - VCL 可以在使用 Explorer 内的 VCL 窗口作为进程主机的 shell 命名空间扩展中使用吗?

如果是这样,在这种情况下如何处理 VCL 线程不安全的问题?

4

2 回答 2

4

VCL 确实不是线程安全的。在 VCL 应用程序之外运行并不能缓解该规则。缺少一个主 VCL 线程只会让事情变得更糟;VCL 控件期望在主线程的上下文中运行,一般来说,没有这样的线程,也不可能有。您正在使用的控件在没有任何同步保护的情况下访问各种全局变量,除了修补任何 VCL 控件使用的所有单元之外,您无能为力。

使用常规的 Windows API 技术,而不是 VCL 函数,在资源管理器中创建和操作窗口。


您可以通过确保在被告知时检查队列来解决同步挂起问题,但是如果没有“主”线程,则不清楚您将什么进行同步,因此Synchronize可能不是适合该工作的工具。

于 2013-02-28T05:01:15.940 回答
0

我们终于能够解决这个问题。固定的 shell 命名空间扩展将在即将推出的 MagicRAR 9.0 中提供。问题确实出在 VCL 上——否则我们的代码非常好。对于任何其他尝试使用 Delphi 构建 shell 命名空间扩展的人:

Yes, you can build shell namespace extensions with Delphi. BUT - if you are using the VCL, you will experience countless random crashes and instability. AND - if you are are not using the VCL, there's little point to using Delphi. The good news is you won't need to patch the VCL sources. Just use a dedicated VCL thread.

于 2013-05-28T14:05:28.760 回答