我想了解 COM DLL 运行中的一些意外行为,其中出现静态 C++ 数据正在跨多个进程共享。环境有点复杂,对各种COM线程模型的理解也比较薄弱,希望有人能帮忙。
环境
- 64 位操作系统上的 IIS 服务器运行多个 C# 网络服务,每个服务都在其自己的 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 静态数据拷贝,但事实似乎并非如此。
有人可以解释静态数据最终是如何在进程之间共享的吗?
我怎样才能避免这种情况? (除了重构代码以删除所有静态数据,目前这并不可行)
最佳答案
如果您看到 COM 对象之间共享数据,则意味着它们托管在同一进程中。是的,可以在进程之间共享数据,但不是偶然的。由于您的应用程序池是不同的进程,因此一定是这些 COM 对象托管在进程外,而只是加载到应用程序池中的 stub 。
如果您可以控制 Utilities.dll(听起来您确实可以),我会尝试添加一些调试信息以找出托管 COM 对象的进程 ID。我希望您会发现它与应用程序池 ID 不匹配,并且您将能够使用该 ID 来了解发生了什么。
理想情况下,设计良好的 COM 对象位于何处无关紧要,这应该是某种实现细节。是否可以取消共享数据结构?
关于c# - COM DLL 依赖项中静态 DLL 数据的多个进程和拷贝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15360461/