【问题标题】:Architecture: How to serve multiple COM interfaces that access a shared resource架构:如何为访问共享资源的多个 COM 接口提供服务
【发布时间】:2011-08-30 00:38:57
【问题描述】:

我有一个架构问题。我有一个概念上是这样的项目:

这看起来很简单,但有一些皱纹。一些背景,通过一个部分虚构的例子。这是一个ASCOM driver,它控制一些电机、传感器和一些电源开关。硬件设备可以旋转天文台并报告其位置,打开和关闭快门以及打开和关闭各种观测仪器(望远镜、照相机、调焦器等)的电源。

硬件抽象层处理通过串行链路发送和接收命令以及随之而来的任何时序和排序问题。表示层可以调用 HAL 中的方法来使硬件执行某些操作,这可能会在串行端口上生成一系列命令和响应,或者根本不生成。未经请求的数据也可以到达串口,完全在 HAL 内处理。

“表示层”由几个 COM 接口组成。一个接口 (IDome) 处理控制圆顶和快门,另一个接口 (IPower) 处理各种设备的电源控制。这是一个标准,不能更改。

当两个不同的程序想要访问该设备时,问题就出现了。例如,一个程序可能想要通过 IDome 接口控制球机,另一个程序可能想要使用 IPower 接口控制电源。在当前的实现中,这会导致整个程序集的两个实例在不同的进程中创建,一个因串行端口争用而失败,只能允许一个连接。

我需要找到一种将 HAL 和表示层解耦的方法,使得 COM 接口可以被多个进程加载,而 HAL 只加载一次并服务于表示层的所有实例。

目前所有这些“层”都包含在一个 .NET 程序集中,如果可能的话,我更愿意保持这种方式。

什么模式适合这种情况?非常感谢任何和所有建议。

【问题讨论】:

  • 嗯,那么当两个程序都想使用 IDome 时会发生什么?这往往很快就会以与 SerialPort 处理它的方式完全相同的方式结束:先到先得,对其他所有人拒绝访问。
  • 它并没有那么糟糕,因为 HAL 实际上主要处理缓存数据,因此实际上不存在资源争用。唯一的争论点实际上来自 HAL 必须打开串行端口这一事实。此外,在这种特殊情况下,多个程序访问同一个界面是不正常的,多个程序将各自访问不同的界面。其中一些架构已有 10 多年的历史,并且早于 .NET,所以它有点尴尬。
  • 一个程序使用 IDome 对月球进行成像,另一个使用它对火星进行成像。应该怎么会有好的结局?有资源争夺,只有一个穹顶。
  • 如果你有一个集中的进程来控制它,请求不仅可以指定目标(火星),还可以指定源。如果该位置不再是源,您可以提供一个很好的错误。这样,有人可以请求拍摄火星的图像,但前提是该客户和用户明确将其从月球上移开。

标签: .net design-patterns architecture ipc interprocess


【解决方案1】:

一种选择是使需要成为单例(HAL)的东西实际上是盒子上的单例。例如,您可以将 HAL 逻辑移动到 Windows 服务中,并且表示层可以通过进程间通信(管道或 tcp 套接字)进行通信。为确保只有一个服务实例启动,您可以强制使用静态服务名称,但您也可以通过让服务采用系统范围的互斥体来防止服务实例在多个用户会话下运行。

【讨论】:

  • 这似乎是一个合理的解决方案。您将如何处理 IPC 方面?是否有必要将所有内容都作为字符串传递,或者(比如说).NET Remoting 是一种选择?或者这些天远程处理已经过时了?我想我要问的是,'有没有办法只调用服务'?
  • 对于 .Net,.Net 远程处理很好。另一个选项是 WCF,它允许您定义数据协定(使用属性装饰您的类和属性)并且传输是可配置的。 WCF 允许您在自己的进程中托管许多不同类型的服务(Windows 服务)。例如,使用 config,您可以在 pox(普通的旧 xml)、soap 或二进制文件之间切换。我相信它还允许 tcp 传输...
【解决方案2】:

您也许可以使用DCOM。这个想法是将您的 CLSID 注册为进程外服务器(可选地使用COM+)。当您的客户端创建这些 CLSID 的实例时,它们都将在“代理进程”中创建,并且 Windows 将透明地编组客户端进程与此代理进程之间的调用。

请注意,要执行此操作,您的界面必须有一个“proxy/stub DLL”。如果您编译包含接口定义的 IDL 文件,它将为此类代理/存根 DLL 生成 C 代码。然后,您必须注册此 DLL 以实现进程外通信,才能与您的自定义接口正常工作。

或者,您可以在 HAL 级别应用相同的进程外激活模型 - 即,为 HAL 创建一个 COM 接口,将 HAL 的 CLSID 注册为进程外服务器,并让您的内部组件通过 DCOM 进行通信。这样做的好处是您可以控制接口 CLSID,并且可以注册自己的代理/存根 DLL,而不会与其他供应商的代理/存根 DLL 发生冲突。

【讨论】:

    【解决方案3】:

    就模式而言,您需要一个控制对 HAL 的所有访问的代理,这是给定的。

    在控制访问方面,多个 UI 控制一组资源是否有意义?假设你也想要代理使用的逻辑来解决冲突等。

    或者,您可以为代理设置两个逻辑部分,一个接受输入,另一个报告当前值,以便多个订阅者客户端 (UI) 可以及时了解 HAL 所在的位置。事件驱动的方法在这里可以很好地工作,还可以查看发布/订阅模式。对于单个控件,请查看锁定模式。

    在所有情况下,代理都是应用控制逻辑的地方,但代码结构本身会比这更复杂。

    【讨论】:

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