并行连接到同一COM服务器的多个实例

时间:2012-10-04 13:26:02

标签: c# .net com interop

我写了一个C#程序,它与COM服务器进行通信以进行模拟。它没有任何问题,但是COM服务器执行的模拟是处理器密集型的,只能运行单核。

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

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

修改

我连接到COM服务器的过程是:

  • 使用Project-> Add References-> COM(VS2010)
  • 添加引用
  • 使用以下代码实例化模拟器对象:

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

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

COM服务器是一个dll。

2 个答案:

答案 0 :(得分:2)

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

根据您的描述,问题似乎是DSS实现使用一些静态/全局状态,这会导致执行并行化时导致数据乱码。

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

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

所有这一切,在去那里之前确保问题不在调用者方面,即你的并行化而不是服务器本身。

答案 1 :(得分:1)

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

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