【问题标题】:Transfer large data between .net applications on same computer在同一台计算机上的 .net 应用程序之间传输大数据
【发布时间】:2012-03-13 17:23:26
【问题描述】:

我有两个在同一台机器上运行的 .net 应用程序。 第一个应用程序是“引擎”。它构建图像 - 图像的大小约为 4M。 第二个应用程序是“查看器”。它显示了“引擎”发送的图像。 引擎每 10-15 秒发送一次图像。

我的问题是将图像从引擎传递给查看器的最糟糕的方法是什么。 目前,我正在为此使用 FileSystem。引擎将图像写入文件系统文件夹,查看器使用 FileSystemWatcher 获取此文件。

这种方法可以吗?这靠谱吗?

【问题讨论】:

  • 看来需要用到IPC:switchonthecode.com/tutorials/…
  • 这如何解决问题? WCF 会增加很多开销,特别是如果它需要在进程中托管。
  • 它可能会增加开销,但它是跨进程通信的有效替代解决方案。也就是说,我认为这是一种替代方案,不一定是对当前文件系统使用的改进。
  • IPC 旨在在进程之间传输数据。我不认为文件系统是可靠的。你可能会遇到文件锁,你可能没有足够的可用空间等。文件系统观察器也不是很可靠:stackoverflow.com/questions/239988/…
  • 在这里学究气......你自己的单元测试应该证明它是否既可行又可靠。

标签: c# .net filesystems communication filesystemwatcher


【解决方案1】:

由于 .NET Framework 4.0 您可以为此使用内存映射文件,我相信它会比基于文件系统的方法更快,因为您不需要昂贵的文件系统 IO 操作。

内存映射文件包含虚拟文件的内容 记忆。文件和内存空间之间的这种映射使 应用程序,包括多个进程,通过以下方式修改文件 直接读取和写入内存。 内存映射文件可以在多个进程之间共享。进程可以使用创建文件的进程分配的通用名称映射到 > 相同的内存映射文件

所以要跨多个进程共享 MMF,您只需要共享一个 MMF 名称,因此您可以考虑以下方法:

有用的链接:

(来自上述文章)如果我们检查其他 IPC 方法,我们可以看到以下架构:

【讨论】:

    【解决方案2】:

    有很多不错的选择:

    • 消息队列
    • 命名管道(直接)
    • 内存映射文件
    • 命名管道或 MSMQ 上的 WCF

    其中任何一个都足够快,所以我建议最容易实现。

    在我看来,消息队列 (MSMQ) 使用起来最简单,为您提供对象传输(与流相反)并为您提供可选的传输持久性(在发送方或接收方未运行的情况下很有用)。所有这些对于 WCF over MSMQ 来说都是正确的,但 WCF 意味着更多的开销、复杂性和涉及的配置,并且没有额外的(在这种情况下)价值。

    这样发送:

    MessageQueue queue = new MessageQueue(".\\private$\\ImagesQueue");
    Message msg = new Message
    {
        Formatter = new BinaryMessageFormatter(),
        Body = myImage,
        Label = "Image"
    };
    queue.Send(msg);
    

    接收:

    MessageQueue queue = new MessageQueue(".\\private$\\ImagesQueue");
    msg = queue.Receive(TimeSpan.FromMilliseconds(100));
    if (msg != null)
    {
        msg.Formatter = new BinaryMessageFormatter();
        myImage = (MyImage)msg.Body;
    }
    

    使用前需要创建队列。您可以在应用程序启动时执行此操作

    在你的课堂上有这个:

    private const string queueName = ".\\private$\\ImagesQueue";
    

    并且在应用程序初始化/启动中确保你有你的队列:

    if (!MessageQueue.Exists(queueName)
    {
        MessageQueue myQueue = MessageQueue.Create(queueName);
    }
    

    使用这种队列机制,引擎不必等待查看器完成。这将大大提高感知性能,因为您可以在仍查看前一张图像的同时生成下一张图像(实际上是其中的数量)。使用内存映射文件实现起来并不容易。

    MSMQ 是标准的 Windows 组件,但需要在 Windows 功能中启用。

    【讨论】:

    • 谢谢。我喜欢 Message Queue 方法,因为您写道:“在我看来,Message Queue (MSMQ) 最简单易用,为您提供对象传输(与流相反)并为您提供可选的传输持久性(在发送方或接收方未运行的情况下很有用) )。”谢谢。
    • 很高兴能帮上忙。我已经扩展了我的答案,详细介绍了如何在应用启动时创建队列。
    【解决方案3】:

    是的,这是一种有效的方法。并且假设您的代码不包含错误,是的,它是可靠的。

    但它很慢。如果吞吐量是一个问题,您可能需要使用套接字(如果您想将引擎和查看器拆分到不同的机器)或命名管道(用于同一台机器上的进程间通信)。

    【讨论】:

      【解决方案4】:

      使用ZeroMQ。它非常易于使用(如果您只发送一种消息,则比 WCF 更容易),没有太多开销,并且通常可以很好地解决许多进程间通信问题。

      【讨论】:

      • 我不认为 ZMQ 在这种情况下是一个很好的选择 - 当您发送许多小消息时,ZMQ 非常棒 - 并且不必保证它们的接收顺序(或即使他们到达了所有)。适用于每秒更新 60 次的股票行情。在这种情况下,尽管我们每 10-15 秒发送一条非常大的消息 - ZMQ 并不适合这种用例。
      • 是的,但是您在同一台机器上的两个组件之间发送消息。您不会遇到任何与 UDP 相关的数据丢失。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-09
      • 1970-01-01
      • 2010-10-15
      • 1970-01-01
      相关资源
      最近更新 更多