【发布时间】:2014-04-29 14:07:45
【问题描述】:
我的 C# 应用程序正在使用非线程安全的本机代码。
我可以运行该本机代码的多个进程,使用进程间通信来实现并发。
我的问题是,我可以改用 App Domains,以便多个托管线程(每个线程位于不同的 App Domain)将调用本机代码并且它们不会相互干扰吗?
主要目标是防止进程分离。
【问题讨论】:
标签: c# .net multithreading native appdomain
我的 C# 应用程序正在使用非线程安全的本机代码。
我可以运行该本机代码的多个进程,使用进程间通信来实现并发。
我的问题是,我可以改用 App Domains,以便多个托管线程(每个线程位于不同的 App Domain)将调用本机代码并且它们不会相互干扰吗?
主要目标是防止进程分离。
【问题讨论】:
标签: c# .net multithreading native appdomain
不,AppDomain 是纯托管代码概念。它通过保持托管对象根分开来实现隔离。一个 AppDomain 无法看到另一个 AppDomain 的对象,这使得中止代码和卸载程序集非常安全。绝不会发生意外,它会丢弃所有可能包含状态的数据。
非托管代码完全不依赖 GC 堆,因此 AppDomains 将在其数据部分和自己的本机堆 (HeapAlloc) 中进行分配。这种分配是进程全局的。这使得进程成为隔离边界,您需要一个辅助进程来加载 DLL 并使用 .NET 进程互操作机制之一(套接字、命名管道、内存映射文件、远程处理、WCF)与之对话。
从技术上讲,您可以创建 DLL 的副本,每个副本具有不同的名称。但这扩展性很差,并且 pinvoke 非常尴尬,因为您不能再使用 [DllImport] 了。您需要为每个导出的函数和 LoadLibrary() 和 GetProcAddress() 声明委托来初始化委托对象。
【讨论】:
是的可以做到,但您应该认真衡量是否通过福利来回报努力。
Windows 不会加载 非托管 DLL 的多个副本,并且非托管 DLL 会按进程加载(而不是按 AppDomain)。您可以做的是为同一 DLL 创建多个临时副本,然后使用 LoadLibrary() 加载它们。
每个进程都将加载每个进程,但它们将彼此分离(因此它们将是线程安全的)。所有这些东西都可以绑定在一个包装非托管调用(LoadLibrary、FreeLibrary、GetProcAddress 和调用本身)的类中。它将使用更少的资源,并且比多个进程更快,但您必须放弃 DllImport 的使用。
我看到的唯一好处是,如果您重用保留缓存的实例(保留进程缓存比保留对象缓存更难),这将比多个进程更好地扩展(因为它使用的资源更少)。
【讨论】: