我工作的公司希望为某些软件提供一些功能,因为它可以应用于多种产品,并且这些产品是用不同的语言编写的,虽然都只在 Windows 上运行,但在 COM 服务器中实现它似乎是一个不错的选择。我使用 python 和 pywin32 扩展编写了 COM 服务器,因此访问它是后期绑定,我相信 IDispatch。
我现在正在尝试为 COM 服务器创建 Java 绑定,因为它需要使用调度接口,所以我决定使用 JACOB 来访问 COM(它似乎是最近更新的项目之一,并且符合我们的需求)。作为 COM 的新手,在 COM 服务器包装的库中并没有真正看到多线程的任何问题,起初我很少关注 COM 线程,所以它是 COM 对象的 Java 绑定,我没有使用提供的任何线程东西通过 JACOB,它的简单测试在 Oracle 的 JVM 中运行良好。
然而,很明显我不能忽略 COM 线程。一个问题是 Java 产品是使用 Excelsior Jet 编译的,由于某种原因,它没有在 Java 中释放 COM 对象,因此 COM 服务器(它是一个单独的 .exe)在退出应用程序后继续运行。另一个问题是我们确实需要使用来自多个线程的 COM 对象,我最初的方法是解决 COM 对象不能在多个线程中使用的问题。
我已经阅读了 JACOB 发行版中关于它如何处理 COM 对象的文档(关于引用计数 VS GC 的文档和关于多线程的文档)。我相信我了解这些以及如何在多个线程中使用 COM 对象并正确释放它们(对每个线程使用 JACOB 的 ComThread.Release() 确实会导致 Excelsior Jet 也释放 COM 对象)。
我的想法是 COM 服务器应该可以使用多线程单元,因此根据 JACOB 文档,这仅需要每个线程在使用 COM 对象之前调用 com.jacob.com.ComThread.InitMTA() 然后调用 com.jacob .com.ComThread.Release() 在每个线程结束时使用 COM 对象。该文件还建议我可能希望 JACOB 创建一个主 STA,因此这也意味着在应用程序关闭时调用退出主 STA。
我的问题是,这个在线程开始时调用的东西似乎不太适合 Java 的做事方式,有什么办法可以尝试将应用程序的其余部分与 COM 的这些特性隔离开来,特别是在穿线区?
我考虑过,由于应用程序正在使用我的绑定而不是直接使用 COM 对象,这些东西可以在那些包装类中处理吗?但是,我似乎只在访问 COM 对象的包装对象的每个方法中调用 ComThread.InitMTA() 和 ComThread.Release()。这感觉效率低下,但是我不知道对 ComThread.InitMTA() 和 ComThread.Release() 的调用实际上做了多少,所以它可能不像最初看起来那么糟糕。
我的另一个想法是,它在使用这个库的早期阶段,我认为我们实际上并没有使用 COM 服务器发布任何东西,所以可能有更好的技术可以使用(例如 RPC,可能是 XMLRPC)?目前做出这样的改变可能不会太痛苦。
为了提供一些关于该库正在做什么的上下文,它主要将各种语音输出 API 包装成一个(例如,提供一个用于访问 SAPI4、SAPI5 和其他一些的通用接口)。所以大多数电话只是告诉系统说点什么,让语音静音或更改设置。一般来说,与库的通信非常简单(我认为返回一个字符串数组就像它得到的一样复杂)。