2012-10-04 31 views
0

我写了一个C#程序,与COM服务器进行交谈来进行模拟。它的工作原理没有任何问题,但COM服务器进行的模拟是相当处理器密集型的,只能运行单核。并行连接到同一个COM服务器的多个实例

因此,我用Parallel.For在多个线程之间分配工作负载。然而,似乎COM服务器生成的所有仿真结果都是在其所有类的实例之间共享的,所以当我只用一个线程运行并行任务时,一切都按预期工作,但是当我运行任务有多个线程,结果是完全乱码的(因为多个线程正在有效地导致仿真引擎在读取时将其结果替换为新结果)。

我想知道是否有多种方式连接到COM服务器多次,以停止类实例的结果共享?

编辑

我连接到COM服务器进程是:

  • 使用项目 - >添加引用 - > COM(VS2010)
  • 使用添加参考以下实例化模拟器对象的代码:

    dss = new OpenDSSengine.DSS(); 
    dss.Start(0); 
    

上述代码在本地线程数据初始化程序(localInit)参数Parallel.For中调用,因此会为每个线程创建一个新的dss对象,但获得的结果似乎在所有线程中都是通用的。

COM服务器是一个DLL。

+2

显然你的COM服务器不是线程安全的。当您多次使用* new *时,您已经获得了多个实例,但仍然不是线程安全的,这非常常见。例如,那些实例可能共享全局变量。没有什么神奇的公式来解决这个问题,在自己的进程中运行每个实例并与之交谈,比如说WCF可以工作。痛苦。 –

+0

你确定这是一个多线程的COM服务器(即不在STA中运行)吗?什么阻止你创建COM服务器的多个实例(COM服务器是一个对象,而不是一个进程)?它是一个超出proc服务器(.exe)或in-proc(dll)吗?你如何获得COM对象?它可能是单身COM服务器(例如,通过使用DECLARE_CLASSFACTORY_SINGLETON)。请提供更多信息 –

+0

谢谢,相应地添加了以上评论。 @ZdeslavVojkovic,创建COM服务器的多个实例的想法听起来像它会工作,但我还没有找到一种方法来使用上述方法来做到这一点。如何做到这一点? –

回答

1

当您指定您的COM服务器实际上是一个进程内服务器(.dll而不是.exe)时,这意味着您每次执行new DSS()时都会创建一个新实例(除非它是使用单例类创建的工厂,这是罕见的,但可能)。

根据你的描述,这个问题似乎与事实上DSS实现使用一些静态/全局状态,当你并行执行时会导致数据出现乱码。

在这种情况下,您可以使用DllSurrogate在单独的进程中运行服务器的每个实例。如果默认代理(dllhost.exe)不够,it is possible to write the custom one。请注意,将服务器移动到另一个进程将为针对服务器完成的每个方法调用引入编组开销。

如果您使用的是STA COM server,请不要这么说,因为所有对服务器的调用都是由COM基础结构进行序列化,所以并行化将不起作用。

所有的说法,在去那里之前,确保问题不在调用方,即使用并行化而不是服务器本身。

+0

谢谢! –

1

首先尝试创建COM对象的多个实例(只需多次调用新的OpenDSSengine.DSS(),将结果存储在单独的变量或数组中)。如果COM服务器实现的很好,这些多个实例将共存在您的进程中而不会相互干扰,并且您的多线程客户端代码可以同时使用它们。

如果您仍然发现这些实例互相干扰,这意味着COM服务器正在使用某个过程的全局状态。正如其他人所建议的那样,解决这个问题的唯一方法就是通过多个代理过程调用多个COM对象。

相关问题