|
简介 您对 Windows CE 设备上的进程间通讯 (IPC) 限制感到失望吗?在其他 Windows 平台上,IPC 通过命名管道(本机)或远程处理(托管)的方式实现;这些选项都不能用于 Windows CE。本文说明点对点消息队列 — 一个鲜为人知的 IPC 机制,它高效、灵活,并且专用于 Windows CE 4.0 及其更高版本。此外,本文还说明如何设计和使用托管包装,使 .NET Compact Framework 应用程序中的 IPC 极其简便。 开发人员能够以多种方式使用点对点消息队列。开发人员通常在无法宿主 .NET Compact Framework 运行库的情况下使用 IPC 作为替代方案(本机进程通过 IPC 与托管进程进行通讯),并且点对点消息队列是最佳选择。点对点消息队列还可以与操作系统进行交互,例如,用于获取电源信息。本文不介绍点对点消息队列的其他用途,这些用途留待您了解核心原理之后自行探究。 本机 API 概述 本部分以一个您易于了解的方式描述点对点消息队列函数。要从 MSDN 上查看该应用程序编程接口 (API) 中的 6 个函数和 2 个结构,请参阅 Message Queue Point-to-Point Reference。 当开发人员使用 IPC 时,一个进程创建用于写入的队列,另一个进程创建用于读取的队列 (CreateMsgQueue)。在双向 IPC 通讯中,开发人员在通讯的每一端(在两个独立的进程间或同一进程的两个对象间)都需要两个队列。 在使用点对点消息队列时,开发人员可以采用若干种方法。例如,有用于读取 (ReadMsgQueue)、写入 (WriteMsgQueue) 和关闭队列 (CloseMsgQueue) 的方法。此外,如果除了队列句柄之外,开发人员还具有拥有该队列的源进程的句柄,那么他们就可以打开现有队列 (OpenMsgQueue)。开发人员可以查询一些统计信息 (GetMsgQueueInfo),最后可以使他们的应用程序等待队列句柄 (WaitForSingleObject) 接收信号,以便确定队列中是否有数据。 打开一个现有队列时,开发人员只能指定一个选项 — 该队列是用于读还是用于写。当创建队列时,开发人员可以指定其他参数:名称 (lpszName) 和选项(类型为 MSGQUEUOPTIONS 的 lpOptions)。队列选项包括以下内容:单个消息的最大大小 (cbMaxMessage)、队列中消息的随机最大数量 (dwMaxMessages)、是否应该动态分配缓冲区(dwFlags、MSGQUEUE_NOPRECOMMIT),以及阅读器是否可以在没有编写器的情况下存在(dwFlags、MSGQUEUE_ALLOW_BROKEN),反之亦然。关闭队列时,开发人员将句柄作为参数 (hMsgQ)。 写入队列需要一个指针 (lpBuffer)、消息中的字节数 (cbDataSize)、超时 (dwTimeout),以及该消息是否是一个警告消息(dwFlags、MSGQUEUE_MSGALERT)。从队列读取需要:传入一个缓冲区 (lpBuffer)、缓冲区的大小 (cbBufferSize),以及一个超时值 (dwTimeout);因此,可获悉实际字节数 (lpNumberOfBytesRead) 以及该消息是否为一个警告(pdwFlags、MSGQUEUE_MSGALERT)。注意,超时是以毫秒计算的;0 表示“不阻塞”,而 INFINITE(-1) 表示“阻塞,直到操作完成或队列状态更改”。如果成功,读函数和写函数都返回 TRUE;否则,返回 FALSE。在后一种情况中,您可以获得扩展的错误信息 (GetLastError)。函数返回 FALSE 的可能原因有:缓冲区太小 (ERROR_INSUFFICIENT_BUFFER);没有编写器或阅读器,且开发人员未按前面段落中所述的那样指定 MSGQUEUE_ALLOW_BROKEN (ERROR_PIPE_NOT_CONNECTED);或者发生超时 (ERROR_TIMEOUT)。对于 WriteMsgQueue,如果未按前面段落中所述的那样指定 MSGQUEUE_NOPRECOMMIT,则也可能得到错误 ERROR_OUTOFMEMORY。 可调用 GetMsgQueueInfo 来获得包含统计信息的结构 (MSGQUEUEINFO)。该结构包含的信息包括开发人员在创建队列时传入的一些参数:消息的最大大小 (cbMaxMessage)、消息的最大数量 (dwMaxMessages)、是否应该动态分配缓冲区(dwFlags、MSGQUEUE_NOPRECOMMIT),以及阅读器是否可以在没有编写器的情况下存在(dwFlags、MSGQUEUE_ALLOW_BROKEN),反之亦然。此外,该结构还包含以下内容:当前队列中非警告信息的数量 (dwCurrentMessages)、队列中曾经存在消息的最大数量 (dwMaxQueueMessages)、当前阅读器的数量 (wNumReaders),以及当前编写器的数量 (wNumWriters)。 设计托管接口 在为任何本机 API 集设计托管接口之前,首先需要查看它是否已经实现了。对于点对点消息队列,没有现成的库且搜索结果只提供有关 API 描述的少量信息。由于之前很少涉足该领域,因此描述针对点对点消息 API 的托管包装的设计和实现看起来是值得的。 当开发人员将一组相关 Win32 API 包装到一个或多个托管类中时,会使用一个通用模式;大多数 Windows API 都操作一个句柄(并将其视为它们的第一个参数)。从面向对象的角度看,可将该句柄看作对象标识。您可以将与句柄相关的所有方法分组到公开相同方法的类中。除不需要该句柄之外,这些方法拥有与原始方法相同的签名。该句柄在对象创建时获取,在对象处置/析构时关闭。在 .NET Compact Framework 中,句柄由 IntPtr 类型表示。因此,根据前面的信息,您可以按以下方式创建包装特定本机 API 的类。
+ constructor(String name, MsgQueueOptions opt) + ReadMsgQueue(byte[] buf, Int32 bufSize, Int32 numRead, Int32 timeout, Int32 flags) + WriteMsgQueue(byte[] buf, Int32 bufSize, Int32 timeout, Int32 flags) + GetMsgQueueInfo(MsgQueueInfo info) + Close()
|
|
|
|
|
|