【问题标题】:C# External library using static members preventing multithreadingC#外部库使用静态成员防止多线程
【发布时间】:2013-07-04 11:06:36
【问题描述】:

我正在使用一个库,该库是为基于输入数据执行模拟而创建的,具有单个入口点,例如 Run(Data data)

但是不幸的是,库内部将值存储为静态成员(我不知道为什么,但我无法更改它),因此在尝试同时执行多个模拟时会出现问题,因为多个线程正在影响内部数据相同。

我想同时运行多个模拟的原因是为了让用户能够指定一系列值,并将所有输出聚合并以可比较的格式呈现。

最初我认为解决此问题的最简单方法是编写一个简单的控制台应用程序,该应用程序可以作为一个单独的进程生成,以执行计算并转储结果。但是,需要将大量数据加载到内存中才能运行模拟并生成单独的进程,这意味着这些数据需要多次加载,并且比顺序运行模拟要慢得多,并且可能会占用几 GB内存。

所以基本上我正在寻找一种为每个线程创建本地存储的方法,如果我可以修改库,我会查看如下代码:

[ThreadStatic]
public static int Foo { get; set; }

有没有办法指定一个程序集/静态类声明,而不修改它,以使用本地线程存储?或者也许是一种在运行时有效地创建对同一程序集的多个引用的方法?

【问题讨论】:

  • '库内部将值存储为静态成员':((我想知道为什么库开发人员以这种方式削弱他们的代码?
  • 我认为他们将它从一些较旧的代码库移植到 .NET,因此它可能是某种第 3 方编译器的结果。

标签: c# .net multithreading static-libraries .net-4.5


【解决方案1】:

使用单独的控制台应用程序您走在正确的轨道上,但由于启动成本如此之高,您需要一种更复杂的方法。

不要每次都生成一个新的控制台应用程序,而是创建一个可以与之通信的子进程池(通过 stdin/stdout 或其他一些进程间通信,如 wcf、远程处理或命名管道)。创建一个包装器/管理器类来跟踪这些进程,根据需要产生新的进程,并知道哪些进程正在使用中。当一个进程没有被使用时,它可以向它发送一个新的调用并等待结果。

您也可以通过将库多次加载到单独的 AppDomain 中来在内存中执行相同的操作,但我个人认为单独的进程更容易且更安全。

【讨论】:

  • 非常感谢您的建议,打算对这两种方法进行一些阅读,您能否详细说明在同一台机器上使用 WCF 进行进程间通信的性能?此外,加载和卸载新应用程序域的主要安全问题是什么?
  • @AlexHopeO'Connor,我不会担心 IPC 的性能。听起来您正在运行的过程将比任何相关的 IPC 花费更长的时间。不过,您应该考虑可维护性。 MS 绝对建议将 WCF 用于所有通信,包括进程间甚至跨 AppDomain 的通信,但我发现远程处理要容易得多,而且如果您发送的数据比命名管道或标准输入/输出简单,则同样容易。
  • 我不知道多个应用程序域的安全问题。它们非常常用于隔离第三方代码和插件。我个人觉得管理多个进程更容易,但我在处理应用程序域方面的经验有限(在单元测试环境中)。
  • 我将使用应用程序域方法,因为在进行了一些测试之后,当尝试通过命名管道共享数据并且没有共享内存时,每个进程仍然需要 WCF 有点太慢加载整个数据集,而不是仅加载更改的模拟参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-10
  • 2014-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-02
  • 1970-01-01
相关资源
最近更新 更多