在同一台计算机上,在.NET应用程序之间传输大量数据

14

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

我的问题是,如何从引擎传递图像给查看器最好。 目前,我使用FileSystem进行此操作。 引擎将图像写入文件系统文件夹,查看器使用FileSystemWatcher获取此文件。

这种方法可行吗? 这可靠吗?


这怎么解决问题的?WCF增加了相当多的开销,特别是如果需要在进程中托管。 - Oded
IPC旨在在进程之间传输数据。我认为文件系统不可靠。您可能会遇到文件锁定的问题,也可能没有足够的可用空间等。此外,文件系统监视器也不是非常可靠:https://dev59.com/nHVC5IYBdhLWcg3wnCaA - Archeg
@AdamHouldsworth 我没有注意到原帖中是否提到他们正在使用单元测试。这意味着该声明也有些不相关。 - Grant Thomas
@Mr.Disappointment 不完全是这样。单元测试将有助于证明方法的可靠性和功能成功 - 这是问题的基石。此外,吹毛求疵的观点是,如果他们没有使用单元测试来证明这些东西,那么他们应该这样做。 - Adam Houldsworth
@Mr.Disappointment 这也是我的观点...什么测试呢?这样的测试将首先回答问题。因此,我说我很龟毛,并将其发布为评论。 - Adam Houldsworth
显示剩余4条评论
4个回答

11
自从 .NET Framework 4.0 起,您可以使用内存映射文件来实现此功能。相比于基于文件系统的方法,我认为它会更快,因为您不需要进行昂贵的文件系统 IO 操作。
内存映射文件包含了一个文件在虚拟内存中的内容。文件和内存空间之间的这种映射使得应用程序(包括多个进程)能够通过直接读写内存来修改文件。内存映射文件可以被多个进程共享。进程可以通过使用由创建文件的进程分配的公共名称来映射到同一内存映射文件。
因此,要在多个进程之间共享 MMF,您只需要共享一个 MMF 名称,因此您可以考虑以下方法:

有用的链接:

(从上述文章中提到的)如果我们检查其他IPC方法,我们可以看到以下架构:enter image description here

7

有一些很好的选择:

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

这些选项中的任何一个都足够快,所以我建议选择最容易实现的。

在我看来,消息队列(MSMQ)是最简单易用的,它可以提供对象传输(而不是流),并且可以提供可选的传输持久性(在发送方或接收方未运行的情况下非常有用)。所有这些对于使用MSMQ的WCF也是正确的,但是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功能中启用。

谢谢。我喜欢消息队列的方法,因为你所写的:“在我看来,消息队列(MSMQ)是最简单易用的,它可以提供对象传输(而不是流),并且可以提供可选的传输持久性(在发送方或接收方未运行的情况下非常有用)。”谢谢。 - MTs
很高兴能够帮到您。我已经扩展了我的答案,并提供了更多关于如何在应用程序启动时创建队列的详细信息。 - Maciej

1

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


我认为在这种情况下ZMQ并不是一个很好的选择 - 当你有许多小消息需要发送时,ZMQ是非常好的选择 - 并且它们接收到的顺序不必保证(甚至可能根本不到达)。对于像股票行情每秒更新60次的情况非常有用。但在这种情况下,我们每10-15秒钟发送一条非常大的消息 - ZMQ不是这种情况的理想选择。 - MattDavey
是的,但您正在在同一台机器上的两个组件之间发送消息。 您不会遇到与UDP相关的任何数据丢失。 - zmbq

0

是的,这是一种有效的方法。并且假设您的代码没有错误,那么它是可靠的。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接