【发布时间】:2017-07-01 05:03:22
【问题描述】:
假设我已经
- 一个名为
managed.dll的 C# DLL,它是 COM 可见的。- 一个名为
magaged.exe的C# EXE,它使用managed.dll并有一个名为managed.exe.config的app.config。- 一个名为
unmanaged.exe的 C++ EXE,它通过 COM 调用managed.dll,它与 C# EXE 具有相同的 app.config,但在本例中称为unmanaged.exe.config。
managed.dll 具有以下两个测试属性:
public bool IsServerGC
{
get { return System.Runtime.GCSettings.IsServerGC; }
}
public bool AreVeryLargeObjectsAllowed
{
get
{
try
{
long l = 20000;
double[,] d = new double[l, l];
return l * l == d.LongLength;
}
catch { return false; }
}
}
app.config 对于两个 EXE 看起来都是这样的:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<gcAllowVeryLargeObjects enabled="true" />
<!--<gcConcurrent enabled="false"/>-->
<gcServer enabled="true"/>
</runtime>
</configuration>
对于managed.exe,一切都按预期工作。但是对于unmanaged.exe,<gcServer enabled="true"/> 设置被忽略。我不明白为什么?
我可以看到 unmanaged.exe.config 在创建 COM 对象的第一个实例时被加载。它也很好用,通过更改 <gcAllowVeryLargeObjects enabled="true" /> 设置进行了测试。
我使用的是 Visual Studio 2013、Windows 7(64 位)和 .NET 4.6.1。一切都是为 x64 编译的。
知道为什么在 COM 上使用 managed.dll 时会忽略 <gcServer enabled="true"/> 设置吗?
问候 沃尔米希
【问题讨论】:
-
不为人知的事实是 [ComVisible] 服务器仍然使用 .config 文件。但它必须命名为client.exe.config 并复制到与client.exe 相同的目录中。相当不愉快,因为您并不总是控制客户端应用程序,但它比编写自己的 CLR 主机更容易维护,因此您可以在 CLR 开始执行代码之前对其进行配置。
-
@HansPassant,即使 client.exe 不是托管 exe,是否会加载 client.exe.config 文件?是否在进程中加载托管 dll 后立即加载?
-
@HansPassant:我试过了。但它似乎不起作用。在我的 C# DLL 中有一个方法调用 System.Runtime.GCSettings.IsServerGC 来检查垃圾收集模式。 Managed.exe 和 Managed.exe.config 正在工作。 Unmanaged.exe 和 Unmanaged.exe.config 不起作用。
-
是的,如果 client.exe 不受管理,它可以正常工作。他们很少。 “不起作用”并不能帮助我帮助你。名称和位置很重要。当宿主应用程序在 32 位模式下运行时,您无法获取大对象。 SysInternals 的 Process Monitor 可能会带您到某个地方,假设它仍然在您的计算机上正常工作,您应该会看到 CLR 正在搜索 .config 文件。
-
@HansPassant:我现在使用了 SysInternals 进程监视器,我可以看到 Unmanaged.exe.config 在 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\ 之前加载机器配置。我的非托管运行在 64 位模式下。但是在我的 C# DLL 中调用 System.Runtime.GCSettings.IsServerGC 的方法仍然返回 false。我的配置文件如下所示:
还有其他想法吗?runtime>
标签: c# .net visual-studio garbage-collection com-interop