2)静态与过程:这绝对取决于“静态数据”的确切含义。
对于 DLL,“静态数据”是放置在模块内某处的一组字节,由只读标志保护。加载 DLL 的人会看到相同的字节,因为它们是 DLL 本身的一部分。当然,这些数据大多是不可变的,并且在编译/构建时确定。例如,这是如何在程序集中保存和使用“资源”的。
对于 C# 代码,“静态”数据——字段、属性和事件——只是一个全局变量,它们以命名空间和类的形式封装了一些方便的名称。它们不是完全全局的:.Net 有一个 AppDomain 的概念,类似于 JRE 的类加载器,它允许您在同一个进程中运行单独的 .Net 应用程序 - 并且这些应用程序不会覆盖彼此的内存,即使它们完全运行具有相同静态字段的相同代码。更重要的是,您可以使用 [ThreadLocal] 属性标记一个静态字段,以使该字段不是“全局全局”而只是“每个线程全局”,并且您的应用程序中的每个线程都将有其自己单独的“静态”版本字段。等等等等。
如果您说的是进程,则没有办法以我怀疑您想到的形式“通过 DLL 共享和通信”。DLL 共享就是共享公共代码。根据“进程”的定义,数据内存是分开的,数据当然驻留在进程的内存中。
在系统的较低级别上讲,实际上在虚拟内存子系统级别存在一些共享。如果一个代码模块是共享的,系统可能会注意到相同的 99 个进程使用相同的 DLL 文件,并且它可能决定只加载一次,并将该文件的单个页面映射到多个进程内存的相似页面. 这样,它被加载一次并多次使用,并且发生了真正的共享。但是请注意,代码是加载和共享的,而不是动态分配的内存。较低级别的语言能够“利用”这种共享,它们实际上能够解除代码的只读保护并写入代码内存,因此它们的数据会自动传播到共享相同页面的所有进程,但这是目前被认为是邪恶的:)
抛开内存映射不谈,所有这一切都意味着拥有 DLL 对您的通信没有多大帮助。
1)对于线程 - 有可能并且你听起来知道如何,对于进程 - 你不能。时期。看上面。
现在,要解决您的问题:其核心在于您希望在进程之间进行通信。该主题简称为“IPC”或“进程间通信”。首先,处理它的经典方法是:
- 共享内存(将同一个内存页面映射到几个进程,在 C# 中很难看)
- 文件(9 个进程尝试以正确的方式读/写同一个文件)
- 网络/套接字(tcp、udp .. 我认为不需要解释)
- 管道(具有两侧的特殊文件:一侧用于写入数据,一侧用于读取数据;一侧用于一个进程,另一侧用于第二个进程,并且您有一个“通道”,就像单向套接字连接一样)
- 通用数据库(进程写入相同的表,从相同的表读取=它们可以相互通信)
- (web)services (network/sockets/pipes - 用漂亮的 WSDL 接口和代理类封装)
等等。如果您很少考虑如何使用它 - 它变得非常简单:您准备一个特殊的进程来收集来自其他人的所有数据,例如通过管道或网络/套接字连接,然后该进程简单地完成工作一种典型的方式。这是您的“经纪人”或“服务”流程。很难避免这样的过程,因为您希望数据被收集并统一排序 - 必须安排一些东西来安排排序,并且必须有(大部分)手头的数据来执行它。记住这一点后,您可能会注意到服务流程不必分开。您的“工作”进程之一(生成数据)也可以处理排序工作。所需要的只是以某种方式对其进行编排,以便有一个数据接收器,并且每个人都会知道谁是水槽。我将在这里停止故事。
如果不知何故,您开始想知道为什么只有一个接收器以及为什么一个进程必须完全了解所有要排序的数据——实际上这不是必需的。在多核/多进程机器(甚至分布式平台)上使用了相当多的智能排序算法,它们能够对部分进行排序,然后将所有内容粘合在一起,因此几乎可以立即将其作为一个整体进行排序。它们比简单的“通用全局数据接收器服务”更难理解,但是一旦你理解了它们,在基于文件的存储上编写这样的算法可能会比在套接字或管道上编写 IPC 更快/更简单。
但是,利用 C# 库,我想通过web 服务、.Net Remoting 或通用数据库(sql express?mysql?)进行 IPC 对您来说将是一个好的开始。当您对编排许多进程感到满意时,将管道、套接字、memmap 和其他东西留到以后。
选择一种具体的沟通机制并询问它,它会更容易找到/解释。