【问题标题】:Several AppDomains and native code几个 AppDomain 和本机代码
【发布时间】:2014-04-29 14:07:45
【问题描述】:

我的 C# 应用程序正在使用非线程安全的本机代码。

我可以运行该本机代码的多个进程,使用进程间通信来实现并发。

我的问题是,我可以改用 App Domains,以便多个托管线程(每个线程位于不同的 App Domain)将调用本机代码并且它们不会相互干扰吗?

主要目标是防止进程分离。

【问题讨论】:

    标签: c# .net multithreading native appdomain


    【解决方案1】:

    不,AppDomain 是纯托管代码概念。它通过保持托管对象根分开来实现隔离。一个 AppDomain 无法看到另一个 AppDomain 的对象,这使得中止代码和卸载程序集非常安全。绝不会发生意外,它会丢弃所有可能包含状态的数据。

    非托管代码完全不依赖 GC 堆,因此 AppDomains 将在其数据部分和自己的本机堆 (HeapAlloc) 中进行分配。这种分配是进程全局的。这使得进程成为隔离边界,您需要一个辅助进程来加载 DLL 并使用 .NET 进程互操作机制之一(套接字、命名管道、内存映射文件、远程处理、WCF)与之对话。

    从技术上讲,您可以创建 DLL 的副本,每个副本具有不同的名称。但这扩展性很差,并且 pinvoke 非常尴尬,因为您不能再使用 [DllImport] 了。您需要为每个导出的函数和 LoadLibrary() 和 GetProcAddress() 声明委托来初始化委托对象。

    【讨论】:

    • 很好的答案。有没有其他方法可以运行相同的本机代码,以免静态数据发生冲突? (多进程除外)
    【解决方案2】:

    是的可以做到,但您应该认真衡量是否通过福利来回报努力。

    Windows 不会加载 非托管 DLL 的多个副本,并且非托管 DLL 会按进程加载(而不是按 AppDomain)。您可以做的是为同一 DLL 创建多个临时副本,然后使用 LoadLibrary() 加载它们。

    每个进程都将加载每个进程,但它们将彼此分离(因此它们将是线程安全的)。所有这些东西都可以绑定在一个包装非托管调用(LoadLibraryFreeLibraryGetProcAddress 和调用本身)的类中。它将使用更少的资源,并且比多个进程更快,但您必须放弃 DllImport 的使用。

    我看到的唯一好处是,如果您重用保留缓存的实例(保留进程缓存比保留对象缓存更难),这将比多个进程更好地扩展(因为它使用的资源更少)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-25
      • 1970-01-01
      • 1970-01-01
      • 2011-03-26
      • 1970-01-01
      相关资源
      最近更新 更多