【问题标题】:Recommended way of sharing an object between C# processes在 C# 进程之间共享对象的推荐方式
【发布时间】:2014-01-09 21:06:42
【问题描述】:

我已经阅读了很多关于 IPC 在 2 个 C# 应用程序之间的不同内容及其优缺点,但我觉得我的用例还没有得到令人满意的答案。

我有一个已经存在且会经常更改的对象(我正在尝试将我的工具附加到游戏并使用它来调试使用该工具创建的元素)。结果,我不相信序列化是合适的,因为我基本上会无缘无故地每秒对对象进行 60 次序列化/反序列化。结果,管道是不可能的(或者我在这里遗漏了什么?)。

由于游戏在 Unity 中运行,我仅限于 .NET 3.5 技术,因此无法使用新的 .NET4 共享内存类。

所以看起来.NET 远程处理是要走的路。这不太理想 - 我不需要网络支持,我想要共享的对象在内存中,没有真正的理由使用代理和发送消息来更改它的开销。

但是,每个人都链接到的this tutorial 似乎并不好 - 源代码无法编译,当我编译它时它崩溃了。本教程本身没有提及看起来很重要的 Cache 类,即使有源代码,我也看不到它如何适合我的应用程序。有没有更好的资源?这真的是最好的方法吗。

最后,我只能使用 C++ 进行插值,以使用创建共享内存并将对象移入其中的非托管功能。在我进入那个兔子洞之前,我想确认它们确实不是更好的方法。

更新 - 更多信息

目前只是尝试使用 2 个控制台应用程序。但是,最后我有一个 C#/Winforms 应用程序(如果有帮助,这个 is 是 .NET 4.0),我将连接到 Unity 进程(显然我无法控制)。我有一个工具和 Unity 都使用的 DLL。我将有一个允许工具访问对象的类(例如,如果我可以使用管道,我会从 Unity 调用这个类来创建管道,然后从工具连接到管道)。

对象本身本质上代表一个有限状态机,其描述是从 XML 文件加载的。可以从非常少量的数据中重新创建对象。但是,我宁愿避免手动编写使用某种事件/消息系统的解决方案,以使对象在哪个状态处于活动状态等方面保持同步。

【问题讨论】:

  • 快速提问:有问题的两个应用是什么? (即:目标是从统一编译的可执行文件,工具是表单 exe 等)注意:在这种情况下,我可能只是尝试将代码挂钩到目标应用程序中,它会启动一个线程,然后我可以本地控制和访问目标的其余部分......线程可以按我喜欢的间隔向调用者报告。
  • @All 感谢所有答案,我将审查它们并考虑最有效的方法。阅读this 的答案后,我发现拥有共享内存可能还不够,因为列出的原因使我向后移动了一个正方形或 2...
  • @ebyrob 您能否详细说明您的意思/如何在运行中挂钩代码?如果我的理解正确,那听起来可能非常好。
  • 这取决于您可以使用什么。如果您在游戏的插件中,那么您就非常出色。如果没有提供任何东西,那么事情就会回到依赖注入的日子......你用你自己的代码替换已经被调用的东西,它包装了a)预期的东西,b)你的额外东西。 (实际上与进程间部分无关)注意:还有系统调试器和运行时调试工具可以为您提供一些牵引力。
  • Microsoft 认为远程处理已被弃用(请参阅MSDN)。

标签: c# ipc


【解决方案1】:

我认为带有NetNamedPipeBinding 的 WCF 会是一个更简单/更好的选择。

例如here

【讨论】:

  • 这似乎很理想,但是,我在将它与 Unity 结合时遇到了问题。我从 ServiceModel DLL 中得到了各种类型的 TypeLoad 异常(尽管我将 DLL 复制到 Unity 项目中)所以这可能是不可能的......
  • 感谢您的信息!我不确定它如何直接与 Unity 一起工作,但命名管道看起来是最简单的选择。如果您找到解决方案,请进行更新,这将是一个新的学习内容。
  • 只是为了让你知道我必须使用 MemoryMappedFile 是的,看起来 Unity 不喜欢 NetNamedPipes。感谢您的帮助:)
  • @T.Kiley 感谢您的信息:)
【解决方案2】:

我们在这里讨论的是什么类型的数据?如果是符号/度量,则可以将其分隔并存储在内存映射文件中并共享。

由于您使用的是 3.5,因此您不能直接使用 MMF 文件,但 FileMap 应该适合您

https://github.com/tomasr/filemap/tree/master

【讨论】:

  • 我最终使用了 FileMap,因为 NamedPipes 在 Mono Unity 使用的任何版本中似乎都不可用。我还使用this 来同步访问内存映射文件。
【解决方案3】:

在我的公司中,我们使用的解决方案是 XML 对象序列化和 FileSytemWatcher 的组合,它或多或少与命名管道相同,但速度快且运行良好。

【讨论】:

  • 我想避免以任何方式序列化对象,因为这些对象可能有很多,而且它们都会每秒更改 60 次,因此即使是二进制序列化也会导致严重的开销。我希望我的工具基本上是实时的,反映对象的当前状态。谢谢
  • @T.Kiley 60 times a second 对于一台像样的电脑来说不算什么。
  • 嗯,好吧,我以为是这样,在这种情况下,我可以只使用管道和 BinarySerialiser...
  • 使用磁盘 I/O 进行 IPC 比“正确的方法”进行 IPC 更像是一种快速而肮脏的解决方案。您基本上是在通信中添加了一个不必要的中间人(磁盘系统)。易于设置,但如果会有很多沟通,我建议不要这样做。
  • 你是对的,序列化所有这些东西没什么大不了的。最后,我使用了内存映射文件,并在每一帧转储了我需要的所有数据。
猜你喜欢
  • 2021-08-02
  • 2012-07-22
  • 1970-01-01
  • 2020-06-26
  • 2021-10-21
  • 2016-02-05
  • 1970-01-01
  • 2013-05-26
  • 2017-04-22
相关资源
最近更新 更多