【问题标题】:What is the fastest mean to transfer a record in DCOM在 DCOM 中传输记录的最快方法是什么
【发布时间】:2016-12-28 03:00:06
【问题描述】:

我想使用 COM/DCOM 在两台 Windows PC 计算机之间传输一些具有以下结构的记录。我更喜欢一次传输一个数组,比如 100 个 TARec 成员,而不是单独传输每条记录。目前我正在使用 IStrings 执行此操作。我希望使用原始记录来改进它,以节省在两端对字符串进行编码/解码的时间。请分享您的经验。

type
  TARec = record
    A : TDateTime;
    B : WORD;
    C : Boolean;
    D : Double;
  end;

所有记录的字段类型都与 OLE 兼容。非常感谢。

【问题讨论】:

  • 这个问题最好用 winapi 和 c++ 标签来问。这将使您有更好的机会找到 com 专家。如果我是你,我会将 Delphi 记录转换为 C++ 结构。
  • VarArray 类型为 varByte 怎么样?您可以使用VarArrayLockVarArrayUnlock 设置或提取数据。只需使用指针数学或强制转换为表示 array[0..somethingbig] of TARec 的类型的指针即可传递或提取数据。
  • 您好,谢谢 David 的建议,Rudy 我会执行您的建议并反映结果。
  • COM 方式是带有用户定义封送器的 SAFEARRAY 记录。正如 Rudy 建议的那样,您可能会摆脱 blitting,但如果您的字符串是任何其他不可 blittable 类型,则不会。

标签: delphi winapi com


【解决方案1】:

正如 Rudy 在 cmets 中所建议的,如果您的数据包含简单的值类型,那么变体字节数组可能是一种非常有效的方法,而且实现起来也非常简单。

既然您已经声明您的数据已经存在于一个数组中,那么基本的方法是:

  1. 创建一个所需大小的字节数组来保存所有记录数据(使用类型为 varByteVarArrayCreate

  2. 锁定数组以获得一个指针,该指针可以安全地用于引用内存中的数组内容(VarArrayLock 将锁定并返回指向数组数据的指针)

  3. 使用CopyMemory 将数据从记录数组直接复制到字节数组内存中。

  4. 解锁变量数组 (VarArrayUnlock) 并通过您的 COM/DCOM 接口传递它

在另一端(“接收”),您只需颠倒该过程:

  1. 声明所需大小的记录数组
  2. 锁定变体字节数组以获得指向保存字节的内存的指针
  3. 将字节数组数据复制到您的记录数组中
  4. 解锁字节数组

这种确切的方法是我过去在非常苛刻的 COM/DCOM 场景(w.r.t 效率/性能)中非常成功地使用的方法。

注意事项:

  • 如果您的数据曾经更改为包含更复杂的类型,例如字符串或动态数组,则需要额外的工作才能通过字节数组正确传输这些类型。

  • 如果您的数据结构发生变化,那么界面两边上的代码都需要相应地更新。防止这种情况的一种方法是结合一些机制,以便接收器将数据识别为有效或无效。这可能包括例如“版本号”和/或值(在“标题”中作为字节数组的一部分,除了数组数据之外,或者完全作为单独的参数传递 - 精确的细节并不重要)。如果接收器发现它不期望的版本号或大小,那么它可以优雅地报告这一点,而不是天真地错误地处理数据并(很可能)崩溃或抛出异常。

  • 对齐/包装问题。即使记录类型的声明相同,如果使用不同的对齐设置编译代码,那么内存中每条记录所需的大小可能会发生变化(这就是为什么数据结构格式的“版本号”本身可能不可靠的原因)。避免这种情况的一种方法是将记录声明为packed,尽管这是以稍微降低效率为代价的(并且仍然依赖于接口双方同意数据结构为packed)。

不过,有一些事情要记住,而不是规定性的。您的实现需要多么复杂/稳健将取决于您的具体情况。

【讨论】:

  • 这不是一个非常 COM 的答案。 Blitting 结构不是目的。
  • 嗨,大卫,请详细说明您的观点。使用 Rudy 建议的方式会产生什么后果,而 Deltics 试图详细说明它。你介意让我了解更多关于 SAFEARRAY 和自定义编组的信息吗,可能是一些参考 Delphi 方法的链接会很有用。提前谢谢你。
  • @David - 通过 COM 有效地传递 raw 结构是 声明的 意图(明确希望避免在任一端进行编码/解码 - 即编组) .没有提及要求COM Purity,仅(必要时)COM compatibility 和该方法的相对效率。您提到的“非常 COM”方法(在 cmets 中)实施起来会更复杂,将编码/解码字符串换成“非常 COM”编码/解码(称为编组),效率低于“blitting” " 通过一个字节数组来解决 OP 没有的问题。
  • @Zonouzi 您当然可以按照此处建议的方式对数组进行位块传输。只要类型是 blittable 。我相信您也可以通过使用对数组的引用而不是它的副本来避免内存副本。正如 Deltics 所描述的那样,这样做肯定会更有效率。这不是真正的 COM 方式。这是否重要,我不知道。可能不会。
  • 好吧,我的理解是,如果我错了,请纠正我,高效意味着没有 COM 方式,而 COM 方式意味着复杂,因此速度很慢。所以在我的情况下,拥有纯 OLE 兼容的变量类型,与 COM 方式相比,使用 blitting 的缺点是什么。还有什么需要注意的吗?正如我之前所问的,一些关于在 Delphi 中进行 blitting 和 marshalling 的文档的链接会有所帮助。提前致谢。
猜你喜欢
  • 2012-10-19
  • 1970-01-01
  • 1970-01-01
  • 2012-12-08
  • 2011-02-23
  • 2021-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多