背景:
我正在为现有的旧版 C++ MFC 应用程序实现 COM 接口。该应用程序是多线程的,其中一个线程(主线程)用于 COM/GUI,另一个用于来自 C 库的传入事件。COM 接口反映了用户可以使用 GUI 进行的可能交互。
编辑:COM 服务器是“进程外”,即 COM 由 MFC 应用程序实现。
问题描述:
COM 接口具有在树视图控制器中选择对象的功能。选择对象后,用户可以调用 COM 函数,这些函数将使用该对象来执行不同的功能。
示例 1 - 用户看到/感受到的内容:
- 使用 COM 接口中的函数 Y 在树视图中选择对象 X。
- X 在 GUI 中突出显示并且函数 Y 返回。
- 用户调用将删除对象 X 的函数 Z。
编写 MFC 应用程序时,由于各种原因,模型多次与 GUI 回调函数紧密耦合。对于 SelectObject 函数,这意味着在完全执行回调函数之前,不会在树视图中真正选择对象。这意味着示例 1 在现实中看起来更像:
示例 2 - 实际发生的情况:
- 使用 COM 接口中的函数 Y 在树视图中选择对象 X。
- 函数 Y 设置要选择的对象 X 并返回 Y。
- 调用树视图项的回调函数(可能是 OnSelChanged())并更新所有 GUI 元素和应用程序模型以选择 X。
- 用户调用将删除对象 X 的函数 Z。
如果使用普通的 GUI 交互,这对用户来说不是问题;用户在树视图中选择对象 X 后,会在很短的时间内调用回调函数,因此函数 Z 将删除对象 X。
当使用 COM 接口时,这会成为一个问题。当 Y 函数返回时,用户可以选择立即调用 Z 函数。如果回调函数已被调用,对象 X 将被删除,否则会发生意外行为。
这是不受欢迎的行为。像 SelectObject 这样的函数向用户表明,当函数完成执行时,应该选择一个对象,而无需任何额外的等待。
解决方案思路
我一直在试图找出解决这个问题的方法,并提出了一些可能的想法:
- 回调完成时发送事件
- 这是不需要的,因为我仍然认为当函数 SelectObject 执行完成时,用户应该期望选择对象 X,用户不必等待。
- 重写并分离 GUI 和模型。
- 非常想要的东西,但没有时间。GUI 的更新方式与应用程序中的其他所有内容密切相关,需要进行巨大的更改。
- 让 COM 和 GUI 在单独的线程上运行。
- 这个很有趣。我不知道这是否可能;我还没有找到任何信息表明这种分离是可能的。似乎 COM 被锁定只能在主线程上工作。
3号很有趣,但我缺乏知识。有没有人遇到过他们解决的类似问题?我真的很想在这个问题上得到一些帮助:)