0

I've written a C# program that talks to a COM server to conduct simulations. It works without any trouble, but the simulations being carried out by the COM server are fairly processor intensive, and only run single core.

As such, I've used Parallel.For to distribute the workload amongst multiple threads. It appears, however, that all the simulation results generated by the COM server are shared amongst all instances of its classes, so when I'm running the parallel task with only 1 thread, everything works as expected, but when I'm running the task with multiple threads, the results are completely garbled (as multiple threads are effectively causing the simulation engine to replace its results with new ones as they are being read).

I was wondering if there was a way to connect to the COM server multiple times in order to stop the results-sharing of class instances?

Edit

My process for connecting to the COM server was to:

  • Add a reference using Project->Add References->COM (VS2010)
  • Use the following code to instantiate the simulator object:

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

The above code is called in the local thread data initialiser (localInit) parameter of Parallel.For, and thus a new dss object is created for each thread, but the results obtained seem to be common across all threads.

The COM server is a dll.

4

2 回答 2

2

As you specify that your COM server is actually an in-proc server (a .dll instead of .exe), it means that every time you execute new DSS() you actually create a new instance (unless it is created with singleton class factory, which is rare but possible).

The problem, according to your description, seems to be with the fact that the DSS implementation uses some static/global state which results in garbled data when you parallelize the execution.

In that case you can run each instance of the server in a separate process by using DllSurrogate. If the default surrogate (dllhost.exe) doesn't suffice, it is possible to write the custom one. Be aware that moving the server into another process will introduce marshaling overhead for each method call done against the server.

Please also not that if you are using an STA COM server, your parallelization will have no effect, as all the calls to the server are serialized by COM infrastructure.

All that being said, before going there make sure that the problem is not on the caller side, i.e. with your parallelization and not the server itself.

于 2012-10-04T14:35:44.750 回答
1

First try creating multiple instances of the COM object (just call new OpenDSSengine.DSS() multiple times, storing the results in separate variables, or in an array). If the COM server was implemented well, those multiple instances will co-exist in your process without interfering with each other, and your multi-threaded client code can use them simultaneously.

If you still find that those instances are interfering with each other, that means the COM server is using some state that is global to the process. The only way to get around that would be to invoke the multiple COM objects via multiple surrogate processes, as others have suggested.

于 2012-10-04T14:45:08.623 回答