【问题标题】:Fastest way to access VB6 String in C#在 C# 中访问 VB6 字符串的最快方法
【发布时间】:2010-03-30 06:04:38
【问题描述】:

我正在使用 COM 互操作。我在 VB6 中有一个调用,它返回一个大约 13000 个字符的字符串。如果我在纯 VB6 中执行调用,则执行大约需要 800 毫秒。如果我通过 c# 和 COM Interop 执行它,大约需要 8 秒。我假设延迟是由编组引起的。

如果我对编组的看法是正确的,如果有人能建议我将它导入 C# 的最快方法,我将不胜感激。例如会不会更好 a) 将其公开为字节数组 b) 在 VB6 层中提供一个 byref 字符串参数

我也希望能提供一些示例代码。我试过了

Marshal.PtrToStringAuto(Marshal.ReadIntPtr(myCOMObject.GetString, 0)

无济于事。

--

继弗朗西的评论之后。我只是从 C# dll 引用 VB6 dll(所以在处理中)。这是 OLEView 的摘录

interface _MyCOMObect : IDispatch {
        ...
        [id(0x60030006)]
        HRESULT GetString(
                        [in] _IEventHistory* p_oEventHistory, 
                        [out, retval] _IXML** );
        ...
    };

    [
      uuid(09A06762-5322-4DC1-90DD-321D4EFC9C3E),
      version(1.0),
        custom({17093CC6-9BD2-11CF-AA4F-304BF89C0001}, "0")
    ]
    coclass MyCOMObject {
        [default] interface _CFactory;
    };

    [
      odl,
      uuid(C6E7413F-C63A-43E4-8B67-6AEAD132F5E5),
      version(1.0),
      hidden,
      dual,
      nonextensible,
      oleautomation
    ]

我应该指出,参数 (p_oEventHistory) 是另一个我在 C# 中实例化的 COM 对象,但这需要大约 80 毫秒

S

【问题讨论】:

  • 如果您提供一些有关您的 VB6 和 C# 代码的详细信息,这可能会有所帮助。 VB6 组件是进程外服务器还是进程内服务器?您正在访问的对象和属性的实际 TLB 片段是什么。调用是通过 IDispatch 还是常规 COM 接口进行的?您使用的是标准 OLE 编组器还是自定义代理/存根,甚至是自定义编组器?
  • 所以我设法通过不将 COM 对象注入 COM 调用(通过参数)而是在 COM 端进行所有操作,将时间缩短了 1 秒。但是 7 秒对于传输 13000 个字符来说似乎仍然是多余的!
  • 还有其他事情发生。编组 BSTR 需要几微秒,而不是几秒钟。您应该调试VB6代码,将C# exe设置为启动程序。
  • 所以我这样做了,在调用 vb6 函数时设置断点,并在 C# 代码中的返回点设置断点。延迟发生在它离开 VB6 并返回到 C# 之前。我没有提及的另一个因素是 VB6 dll 驻留在 COM+ 中,所以我想知道问题是否出在附近。我不太确定如何开始诊断。谢谢你的建议
  • 这里有一个猜测:COM+ 可能使您的一些对象托管在不同的进程中,这使得编组变慢。

标签: c# string vb6 marshalling com-interop


【解决方案1】:

有几件事:-

  1. 我的 VB6 有点生疏,但您的 IDL 摘录表明 GetString 方法实际上返回了一个实现 IXML 接口的对象。我有点惊讶 Marshal.PtrToStringAuto 可以做任何有用的事情。您能否更改 VB6 以使其实际返回 String 类型的内容?

  2. COM+ 的影响可能是巨大的。首先,我建议您比较第一次调用和后续调用的时间。 COM+ 将需要在第一次调用 VB6 组件时为它启动一个宿主进程,因此第一次调用总是更痛苦。请注意,这发生在第一次调用时,而不是对象实例化时。其次,你的组件在 COM+ 中的配置方式也会产生很大的不同。如果您禁用所有您实际上不需要的 COM+ 服务(例如事务),您可能能够删除 COM+ 在所有方法调用周围放置的一些拦截逻辑。最后,如果您不需要 COM+ 提供的服务,请不要使用它。

【讨论】:

    【解决方案2】:

    我会考虑使用memory mapped files 或命名管道。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-06
      • 1970-01-01
      • 1970-01-01
      • 2011-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-05
      相关资源
      最近更新 更多