14

I have two .net applications that run on the same machine. The first application is the 'Engine'. It builds images - image's size is about 4M. The second applications is the 'Viewer'. It shows the images which the 'Engine' sends. The engine sends images every 10-15 seconds.

My question is what is the bast way to pass the images from the engine to the viewer. Currently, I'm using FileSystem for this. The Engine writes the image to file system folder and the viewer getting this file using FileSystemWatcher.

Is that approach ok? Is that reliable?

tshepang
  • 12,111
  • 21
  • 91
  • 136
MTs
  • 514
  • 5
  • 13
  • Being pedantic here... your own unit tests should prove if it is both OK and reliable. – Adam Houldsworth Feb 23 '12 at 10:09
  • @AdamHouldsworth I didn't notice the OP say they're even using unit tests at all. Meaning that statement was _also_ somewhat irrelevant. – Grant Thomas Feb 23 '12 at 10:22
  • @Mr.Disappointment Not really. The unit tests would go towards proving the reliability and the functional success of the approach - the cornerstones of the question. Also the pedantic point was if they weren't using unit tests to prove this stuff, they should be. – Adam Houldsworth Feb 23 '12 at 10:27
  • @AdamHouldsworth But, _what tests_? That's the point. As far as we know, there aren't any. – Grant Thomas Feb 23 '12 at 10:28
  • @Mr.Disappointment That is also my point... what tests indeed. Such tests would answer the question in the first place. Hence I said I was being pedantic and posted it as a comment. – Adam Houldsworth Feb 23 '12 at 10:28
  • It seems that you need to use IPC: http://www.switchonthecode.com/tutorials/wcf-tutorial-basic-interprocess-communication – Archeg Feb 23 '12 at 10:04
  • How does this solve the problem? WCF adds quite a lot of overhead, in particular if it needs to be hosted in process. – Oded Feb 23 '12 at 10:05
  • It may add overhead, but it is a valid alternative solution for communicating across processes. That said, I'd see this as an alternative, not necessarily an improvement on the current file system use. – Adam Houldsworth Feb 23 '12 at 10:07
  • IPC is designed to transfer data between processes. I don't think file system is reliable. You could stuck with file locks, you may not have enough free space etc. Also file system watcher isn't very reliable too: http://stackoverflow.com/questions/239988/filesystemwatcher-vs-polling-to-watch-for-changes – Archeg Feb 23 '12 at 10:08

4 Answers4

11

Since .NET Framework 4.0 you can use Memory Mapped Files for this, I believe it would be faster than file system based approach since you do not need expensive file system IO operations.

A memory-mapped file contains the contents of a file in virtual memory. This mapping between a file and memory space enables an application, including multiple processes, to modify the file by reading and writing directly to the memory. Memory-mapped files can be shared across multiple processes. Processes can map to the > same memory-mapped file by using a common name that is assigned by the process that created the file

So to share MMF across multiple processes you just need to share a MMF name, so you can consider following approach:

Useful links:

(From the mentioned above article) If we check other IPC methods we can see the following architecture: enter image description here

sll
  • 61,540
  • 22
  • 104
  • 156
7

There is number of good options:

  • Message Queue
  • Named Pipes (directly)
  • Memory mapped files
  • WCF on Named Pipes or MSMQ

Any of those is more than fast enough so I would suggest easiest to implement.

Message Queue (MSMQ) in my opinion is simplest to use, gives you object transfer (as opposed to streams) and gives you optional transport persistence (useful in case sender or receiver is not running). All this is true for WCF over MSMQ but WCF means more overhead, complexity and configuration involved and no additional (in this case) value.

Send like this:

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

Receive:

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

Queue needs to be created before use. You can do that when your application starts

Have this in your class:

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

And in application initialization/startup make sure you have your queue:

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

With this queue mechanism, Engine does not have to wait for the Viewer to complete. This would much improve perceived performance because you can generate next image (actually number of them) while previous one is still being viewed. Not so easy to achieve with memory mapped files.

MSMQ is a standard Windows component but needs to be enabled in Windows Features.

Maciej
  • 7,871
  • 1
  • 31
  • 36
  • Thanks. I like Message Queue aproach becuase what you wrote: "Message Queue (MSMQ) in my opinion is simplest to use, gives you object transfer (as opposed to streams) and gives you optional transport persistence (useful in case sender or receiver is not running)." Thanks. – MTs Feb 26 '12 at 12:33
  • Glad could help. I have expanded my answer with more details on how to create queue in app startup. – Maciej Feb 26 '12 at 15:26
1

Use ZeroMQ. It's very easy to use (easier than WCF if you just send one kind of message), doesn't have a lot of overhead, and in general a good solution to many interprocess communications problems.

zmbq
  • 38,013
  • 14
  • 101
  • 171
  • I don't think ZMQ is a great choice in this scenario - ZMQ is great when you have many many small messages being sent - and the order they are received doesn't have to be guaranteed (or even that they arrive at all). Useful for something like a stock ticker being updated 60 times a second. In this case though we have one very large message being sent every 10-15 seconds - ZMQ is not ideal for this use case. – MattDavey Feb 26 '12 at 15:44
  • Yes, but you're sending messages between two components on the same machine. You won't experience any data loss associated with UDP. – zmbq Feb 26 '12 at 17:08
0

Yes, that's a valid approach. And assuming your code doesn't contain bugs, yes it's reliable.

But it is slow. If throughput is a concern, you may need to use Sockets (if you ever want to split the engine and viewer to different machines) or named pipes (for inter-process communications on the same machine).

Tyson
  • 14,726
  • 6
  • 31
  • 43