1

在注册(RegAsm)我的 C# COM 可见类之后,我发现CoCreateInstance(__uuidof(myclass))仅第一次需要很多时间,随后在同一客户端进程中的尝试立即得到解决。知道为什么要花时间吗?NGen 对我来说不是一个选择。

我的 COM 服务器在 C# 中,客户端在 MFC/ATL

CComPtr<namespace::Imyclass> obj;
hrx = obj.CoCreateInstance(__uuidof(namespace::myclass));
4

3 回答 3

1

第一次调用CoCreateInstance必须加载到进程中并初始化 .NET 运行时。然后,您的 DLL 必须被加载、“验证”并编译成机器代码(尽管即时有助于加快启动速度)。.NET 运行时还必须解析程序集的元数据,然后动态生成和编译“COM 可调用包装器”(http://msdn.microsoft.com/en-us/library/f07c8z1c.aspx),它们是在非托管 COM 世界和托管 .NET 运行时之间架起桥梁的代理。您的代码可能使用的任何其他库也需要加载、验证并可能编译成机器代码(如果不是 NGEN 的话)。

这本质上是一个昂贵的过程。你提到的延误并非闻所未闻。

我不相信你可以做很多事情来加快速度。我建议您考虑是否可以通过在启动后不久创建一个对象来在程序生命周期的早期受到打击。它不会让它更快,但它可能会显着改善用户体验。如果您的程序不能容忍延迟,那么您不应该使用 .NET 来编写 COM 对象(更具体地说,您根本不应该在您的进程中使用 .NET。这不是使用 COM 的问题;它是加载.NET的问题)

顺便说一句,这是在 .NET 中编写 shell 扩展的原因之一……“非常不鼓励”。请参阅有关此主题的最新帖子,其中也涉及 .NET 的启动性能:http: //blogs.msdn.com/b/oldnewthing/archive/2013/02/22/10396079.aspx

(这就是为什么我之前问过您正在运行什么样的客户端。已经运行 .NET 托管代码的客户端依赖于 .NET 运行时并且不会受到这些延迟的影响)

于 2013-04-17T07:08:33.937 回答
0

第一次调用CoCreateInstance可能必须查询注册表和文件系统,加载适当的代码,允许它初始化,最后调用工厂来创建您要求的实例(如果可以找到它)。

第二次调用极大地受益于这些前面的步骤。如果第一次调用成功,则代码已经加载并初始化,它所要做的就是第二次调用工厂。

于 2013-04-17T06:28:31.737 回答
0

如果此延迟仅适用于首次加载(计算机启动后),则这是由加载所有库引起的。启动后的第一次延迟(或长时间不使用 .NET)总是很慢。(见米切利回答)

每次加载也可能导致延迟。今天我发现互联网连接也会导致延迟。

测量值:

  1. 无以太网且无 WiFi 连接延迟:94 毫秒 (Win7) / 1.5 (WinXP)
  2. Windows XP:互联网连接(使用代理和非标准网关;并非所有端口都允许):4-5 秒(WinXP)
  3. 连接到以太网而不是不连接到 Internet:10 秒(Win7)
  4. 连接到以太网后不久(Windows 测试 Internet 连接;网络图标上的蓝色圆圈):30 秒(Win7)
  5. 互联网连接(使用代理和非标准网关;只允许少数端口):30 秒(Win7)

*非标准网关:每台计算机允许的 TCP 端口和连接不同(WinXP 和 Win7 不同)。

在 Windows 7 (x64) 和 WinXP 上测试。我对它进行了测试,因为它来自客户的抱怨,并定位到CoCreateInstance的延迟加载的库在 c# 中并已签名(使用 snk 签名的程序集和用于签署可执行文件的标准证书)

另请参阅:http ://social.msdn.microsoft.com/Forums/sqlserver/en-US/cda45e39-ed11-4a17-a922-e47aa2e7b325/ce-40-delay-when-cocreateinstance-on-pc-without-internet ?forum=sqlce

于 2013-11-25T14:21:08.227 回答