1

我希望了解运行 COM DLL 时出现的一些意外行为,其中静态 C++ 数据似乎在多个进程之间共享。环境有点复杂,我对各种 COM 线程模型的理解相当薄弱,希望有人能提供帮助。

环境

  • 运行多个 C# Web 服务的 64 位操作系统上的 IIS 服务器,每个服务都在其自己的 32 位应用程序池中,因此进程
    • 池具有“启用 32 位应用程序”=True 设置
  • 每个 32 位 C# 服务调用不同的进程内 32 位 COM DLL(因此服务 A 调用 COM DLL 1,服务 C 调用 COM DLL 2。COM DLL 是使用 Qt 4.8 ActiveQt 用 C++ 编写的
  • COM DLL 依赖于许多共享的 32 位 C++ DLL,即 COM DLL 1 和 2 都依赖于 Utilities.dll
  • 据我所知,没有为 COM DLL 设置 ThreadingModel,所以我预计系统将退回到主 STA。
    • 我知道这是不赞成的,但我目前没有足够的知识来改变它。
  • Utilities.dll 包含一些静态 C++ 数据
  • COM DLL 是使用“regsvr32”注册的,并且似乎没有列在“组件服务”中,尽管我对后者的了解很少。

观察到的问题是 Utilities.dll 中的静态数据似乎最终在不同的 IIS 进程之间共享,从而产生了不良后果。我曾预计,由于 COM 位于主 STA 中,它们将被访问,就好像它不是线程安全的一样,每个进程都会获得自己的 DLL 静态数据副本,但情况似乎并非如此。

有人可以解释静态数据是如何在进程之间共享的吗?

我怎样才能避免这种情况?(除了重构代码以删除所有静态数据,这目前并不可行)

4

1 回答 1

1

如果您看到 COM 对象之间共享数据,这意味着它们托管在同一进程中。是的,可以在进程之间共享数据,但不是偶然的。由于您的应用程序池是不同的进程,因此这些 COM 对象一定是托管在进程外的,并且只是加载到应用程序池中的存根。

如果您可以控制 Utilities.dll(听起来确实如此),我会尝试添加一些调试信息以找出托管 COM 对象的进程 ID。我希望您会发现它与应用程序池 ID 不匹配,并且您将能够使用该 ID 找出发生了什么。

理想情况下,精心设计的 COM 对象位于何处并不重要,这应该是实现细节。是否可以取消共享数据结构?

于 2013-03-13T18:09:03.020 回答