将 MFC 对话框从 STA 更改为 MTA

Changing MFC dialog from STA to MTA?

本文关键字:MTA STA MFC 对话框      更新时间:2023-10-16

我正在开发一个具有一些COM接口的API。问题是 API 通过必须由加载该 API 的项目实现的接口进行通信。因此,如果我要使用 API,我会将其加载到我的项目中并创建一个类,该类将实现 API 将调用的方法,以通知我某些事情或向我传递结果。

这显然成了一场编组噩梦。此外,由于还有一些中间对象通过 API 将调用从不同的插件和管理器传递到实现要调用的通知方法的所有对象,这些对象已将自己注册到 API 通知程序,因此在复杂性方面已经失控。

我在想,为了缩短加载 API 的人需要完成的工作,如果 API 遵循自由线程模型,是否有可能让 MFC 生成的类(例如对话框)来实现通知所需的 COM 接口?请记住,这样的对象需要转换为 IStream 并重新转换为 API 端的接口,以便 API 可以调用这些方法。

据我所知,MFC 对话框默认是 STA。有没有办法强制它们在 MTA 中更改或启动?从COM的角度来看,它甚至合法吗?我试图避免创建另一个对象来处理另一个线程中的通知,因为这会使事情复杂化。此 API 需要在多个位置使用,有时在 GUI 中使用,有时在服务中使用等。

我的理解是,API 本身不仅限于控制线程,您的目的是通过 COM 接收器接口获取后台线程上的通知。

三种方法是同时保持COM友好的问题的几种方法。最简单的方法是更改应用程序的全局单元模型,以便将"主"GUI 线程初始化为 MTA。虽然这可能有效,但您可能会很快发现这与其他内容不兼容,例如注册了"Arartment"线程模型的 ActiveX 控件。

另一种选择是稍微违反 COM 线程准则,以便 API 直接从后台线程使用接收器接口,而无需对其进行封送处理。这对于准备在侧线程上接收调用的 MFC 应用程序来说可以正常工作,并且实际上很容易做到(只是 API 端线程/单元之间的自愿传递接收器接口指针)。当 .NET 客户端使用 API 检测跨单元接口指针使用情况时,问题可能会在以后出现。

若要使其对 COM 友好,并且仍然在 UI 线程上使用 STA 线程,可以实现以下方案。API 可以是接受直接传入的接收器接口的 STA 组件(由 STA 中的 MFC 类实现的 COM 对象,甚至更简单的东西,例如直接在窗口类上实现的 COM 接口等)。API 封送将接口指针接收器到 MTA 中,以便在工作线程(CoMarshalInterThreadInterfaceInStream和朋友)上使用。API 使用未封送指针来传递来自 MTA 线程的通知。这通常包括 threda 切换到您不需要的原始线程,因此为了避免这种情况,MFC 端通知类应实现自由线程封送拆收器。这将改变一些事情,以便未封送的接口指针直接在工作线程上接收调用,MFC 应用程序将负责线程同步(关键部分等)。这是 STA、COM 友好的、API 工作线程,同时又高效。