多个线程写入同一dll中的单个数据结构。 (C#)

时间:2012-08-08 20:16:49

标签: c# multithreading dll static filestream

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

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

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

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

修改 非常感谢你们。虽然我可能没有一个确切的解决方案,但你的评论已经指出了一个有用的方向,并清除了我曾经拥有的一些混乱,这就是我所需要的。我认为这个问题得到了回答

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:0)

2)静态与过程:它绝对取决于你的意思是什么"静态数据"。

对于DLL,"静态数据"是一组放在模块内部的字节,用readonly标志保护。加载DLL的人会看到相同的字节,因为它们是DLL本身的一部分。当然,该数据大多是不可变的,并在编译/构建时确定。例如,这是"资源"保存并以组件形式提供。

对于C#代码,"静态"数据 - 字段,属性和事件 - 只是一个全局变量,它们以命名空间和类的形式封装了一些方便的名称。它们不是完全全局的:.Net有一个AppDomain的概念,类似于JRE的类加载器,它允许你在同一个进程中运行单独的.Net应用程序 - 这些应用程序不会覆盖彼此的内存,甚至如果它们使用相同的静态字段运行完全相同的代码。更重要的是,您可以使用[ThreadLocal]属性标记静态字段,以使该字段不是全局全局"但只是"全局每个线程",你的应用程序中的每个线程都有自己独立的"静态"该字段的版本。等等。

如果你说过程,就没有办法通过DLL共享和交流#34;在我怀疑你有你想到的形式。 DLL共享就是共享公共代码。数据存储器是按照"过程"的定义分开的,当然数据存在于过程"存储器中。

在较低级别的系统中,实际上在虚拟内存子系统级别存在一些共享。如果代码模块是共享的,系统可能会注意到相同的99个进程使用相同的DLL文件,它可能决定只加载一次,并且将该文件的单个页面映射到多个流程的类似页面&#39;存储器即可。这样,它被加载一次并多次使用,并发生真正的共享。但请注意,代码是加载和共享的,而不是动态分配的内存。较低级别的语言能够“开发”#34;这种共享,他们实际上能够解除代码的只读保护并写入代码存储器,从而将其数据自动传播到共享相同页面的所有进程,但这当前被认为是邪恶的:)< / p>

将内存映射放在一边,所有这些都意味着拥有DLL并不能帮助您进行多少通信。

1)对于线程 - 这是可能的,你可以听到如何,对于进程 - 你不能。期。见上文。

现在,要解决您的问题:它的核心在于您希望在进程之间进行通信。该主题简称为#IPC; IPC&#34;或者&#34;进程间通信&#34;。对于初学者来说,处理它的经典方法是:

  • 共享内存(将相同的内存页映射到几个进程,在C#中难看)
  • 文件(9个进程尝试以适当的方式读取/写入同一文件)
  • 网络/套接字(tcp,udp ..我认为无需解释)
  • 管道(具有两面的特殊文件:一个用于写入数据,一个用于读取数据;一个用于一个进程,第二个用于第二个进程,并且您有一个&#34;通道&#34;就像一个单向套接字连接)
  • 公共数据库(进程写入相同的表,从相同的表中读取=它们可以相互通信)
  • (web)服务(网络/套接字/管道 - 用漂亮的WSDL接口和代理类封装)

等等。如果您对如何使用它几乎一无所知 - 它变得非常简单:您准备一个特殊的进程,从其他数据中收集所有数据,例如通过管道或网络/套接字连接,然后该过程只需完成工作一种典型的方式。这是你的经纪人&#34;或者&#34;服务&#34;处理。很难避免这样的过程,因为你希望收集和统一排序数据 - 必须安排排序,并且必须有(大部分)手头的数据来执行它。一旦考虑到这一点,您可能会注意到服务流程不必是分开的。你的一个&#34;工作&#34;进程(生成数据)也可以处理排序作业。所需要的只是以某种方式编排它,以便有一个数据接收器,并且每个人都知道谁是接收器。我会在这里停止这个故事。

如果,不知何故,你开始想知道为什么只有一个接收器以及为什么一个进程必须完全了解要排序的所有数据 - 实际上并不是必需的。在多核/多处理机器(甚至是分布式平台)上使用了很多智能排序算法,这些算法能够在部分中执行排序,然后将所有内容粘合在一起,因此几乎可以立即对其进行整理。它们比简单的常见全局数据链服务更难理解,但是一旦理解了它们,可能会在基于文件的存储上编写这样的算法比在套接字上编写IPC更快/更简单或管道。

但是,利用C#库,我认为通过 webservices,.Net Remoting或公共数据库(sql express?mysql?)进行IPC将是一个良好的开端。当您熟悉编排许多过程时,请留出管道,插座,存储器和其他东西。

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