0

我需要设置一个从不同进程和线程接收数据(文本字符串)的 dll。将其放入线程中,将该数据提供给队列以进行排序(来自所有线程的字符串),然后将其存储在文件中。

我可以设置一个dll。我可以设置线程。我可以使我的线程线程安全。我可以将数据放入文件和文件流中。但问题仍然存在:

• 如何设置一组可能是静态的数据,以便多个线程和进程将文本添加到 dll 中的同一个共享数据集?我可以以同样的方式设置文件流吗?如何?

• 单独的进程能否以这种方式使用单个 dll?我认为一个单独的进程将无法看到在 dll 中找到的不同进程的静态数据。有可能吗,还是我必须考虑做一些更复杂的事情?

编辑: 非常感谢大家。虽然我可能没有确切的解决方案,但您的评论为我指明了一个有用的方向,并消除了我曾经遇到的一些困惑,而这正是我所需要的。我认为这个问题得到了回答。

4

3 回答 3

2

我可能误解了您的目标,但根据我所阅读的内容,我可能会建议对流程和线程的结构进行审查。DLL 是每进程的野兽,在每个相关应用程序的进程空间中都加载了一个库。要创建一个从多个进程收集数据的库,需要某种进程间通信机制。交叉螺纹边界是一回事,因为它们是在父进程中管理的,但跨越进程边界是另一回事。Windows 通常不希望进程随意管理其他进程的进程空间。也许,我在想象某种提供感兴趣对象的进程外服务器,因此能够跨多个进程管理它们,但这可能会走上一条不相关的道路。再次,也许我误解了目标,如果我是,我很抱歉。

于 2012-08-08T20:26:15.683 回答
1

一种可能的解决方案是运行单个进程,该进程通过多线程处理提交的 HttpListener 接受数据。线程可以将事件返回给主线程,主线程可以将提供的数据添加到列表或其他数据结构中。

在添加或操作数据时锁定()数据结构可能是一个好主意,以确保您是线程安全的。

此设置将要求您运行单独的进程(可能是服务?),但根据您的要求,无论您使用何种途径,您似乎都必须这样做。

于 2012-08-08T20:56:05.423 回答
0

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 和其他东西留到以后。

选择一种具体的沟通机制并询问它,它会更容易找到/解释。

于 2012-08-08T21:00:07.543 回答