如何在多个Java线程中使用COM服务器

时间:2012-10-15 11:03:45

标签: java multithreading com

我工作的公司需要一些软件的功能,因为它可以应用于多种产品,这些产品是用不同的语言编写的,虽然它们只在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和其他一些的通用接口)。所以大多数电话只是告诉系统说些什么,沉默话语或改变设置。一般来说,与库的通信非常简单(我认为返回一个字符串数组就像它一样复杂)。

1 个答案:

答案 0 :(得分:0)

这听起来像是面向方面编程(AOP)的一个非常好的候选者。 java中的主导框架是AspectJ,但大多数人在Spring-AOP的上下文中使用它。根据您的要求和架构,您可以走向不同的方向:

  1. 编译时编织 - 通过特殊编译器在编译时应用(“编织”)切入点和建议
  2. 加载时编织 - 由JVM代理在运行时应用切入点和建议
  3. 动态代理 - 通过在动态代理外观中包装建议类来应用运行时的切入点和建议(这就是Spring-AOP的工作方式)。
  4. aspectj weaving上找到了相当不错的文章。