2012-10-04 32 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對象。

相關問題