2014-04-29 35 views
8

我的C#應用​​程序使用的是非線程安全的本機代碼。幾個AppDomain和本機代碼

我可以運行的該本機代碼的多個進程,使用進程間通信來實現的併發性。

我的問題是,我可以使用應用程序域來代替,這樣多個管理線程,每個線程在不同的應用領域,將調用本機代碼,他們不會互相干擾?

主要目的是爲了防止過程政企分開。

回答

3

是的它可以完成,但你應該認真衡量,如果努力是由利益償還。

Windows將不加載非託管 DLL的多個拷貝和未管理的DLL每個進程(而不是每個AppDomain)加載。你可以做的是創建同一個DLL的多個臨時副本,然後用LoadLibrary()加載它們。

每一項都會每個進程中加載​​但他們會彼此分開(因此他們將是線程安全的)。所有這些東西都可以綁定在一個包含非管理調用的類中(LoadLibrary,FreeLibrary,GetProcAddress和調用本身)。它將使用更少的資源,並且會比多個進程更快,但是您將不得不放棄DllImport用法。

我看到的唯一好處是,如果您重新使用保留緩存的實例(保留進程緩存比對象緩存難以保留),那麼這將比多進程擴展得更好(因爲它使用更少的資源)。

9

不,AppDomain是一個純粹的託管代碼概念。它通過保持被管理的對象根分離來實現隔離。一個AppDomain無法看到另一個AppDomain的對象,使得中止代碼和卸載程序集非常安全。永遠不會發生意外,它會拋棄所有可能包含狀態的數據。

非託管代碼是完全不可知的GC堆的,因此應用程序域,它會在其數據部分和它自己的本機堆(HeapAlloc)分配。這種分配是過程全球化的。這使得進程成爲隔離邊界,您需要一個幫助程序來加載DLL並使用.NET進程互操作機制(套接字,命名管道,內存映射文件,遠程處理,WCF)與其進行通信。

從技術上講,你可以創建DLL,每個副本有不同的名稱。但是這個規模很小,而且由於你不能再使用[DllImport],所以這個標記非常尷尬。您需要爲每個導出的函數和LoadLibrary()和GetProcAddress()初始化委託對象的委託聲明。

+0

很好的答案。有沒有其他的方式來運行相同的本地代碼,以便靜態數據不會相互衝突? (除了多個進程) – seldary