Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Sharing memory across different running applications

0.00/5 (No votes)
22 Aug 2011 1  
A simple way to share data across your diffrent applications.

Introduction

Sharing memory is a powerful tool and it can now be done simply....

You have an application, we will call it application "A.exe", and you would like it to pass data to your application "B.exe". How would you do this?

  1. You could share a file, but this will be slow and if the data is used a lot, it would put excessive demand on your hard drive.
  2. You could share data across a local network link, but this just adds more overhead for your PC.
  3. You could share some memory, but how?

For example, application "A" is a complex user interface that logs users in, reads databases, and adds user form controls for controlling attached hardware. Application "B" needs to run at the same time within the same PC on another thread/CPU core. It controls hardware in real time via LAN or USB, yet needs data that would require application "A"’s users database results.

Sharing memory in real time is the best way. However this is not as easy as it sounds......

Background

The memory on a PC is fully managed by the Operating System, in this case Microsoft Windows 7. The Operating System has to balance all the different running applications over several CPU cores for all of the running "threads". The application's "A" thread will have no knowledge of the application's "B" thread or its memory use. So how can we set aside some memory to share some data?

In the bad old days of programming, you would have typed "Reserve Memory Address XXX", and in "Basic" would have typed keywords like PEEK or POKE to place the data in. However, if all your applications did this, you soon would have run out of memory, which did happen!

Until .NET Framework 4, sharing memory was hard to do. But thanks to some new functions, it is really easy and your application don’t have to know anything about threads or memory as the new function takes care of the memory, thread safety all for you.

This new shared memory function is handled just like files; you open them with a name, add data to them, and share them across different applications. The data can be a few bytes to Gigabytes. However, I prefer to use a small "buffer file of shared memory". The task of my shared memory file is to pass variables and data from my different applications.

Another example: You could have a shared memory file called "Commands" which is only a few bytes big, sent from application A. Application B reads the commands and replies with its shared memory file called "Results" and puts them ready for application A. The combination is limitless and you can have any number of running applications.

For further reading, please refer to http://msdn.microsoft.com/en-us/library/dd997372.aspx.

Code Description

The code Imports the System.IO.MemoryMappedFiles namespace which has all the classes you need for controlling memory mapped files, and waits for the buttons MakeFile or ReadFile mouse click events to fire.

To write some data to share in memory, you do the following....

Call MakeMemoryMappedFile().

First, you declare an object; I used "File" as a memory mapped file which you can "Open" with the number of bytes you need (e.g., 26), and name it, here I have used "MemoryFile".

Dim File=MemoryMappedFile.CreateOrOpen("MemoryFile",26)

Notice I have used "CreateOrOpen". This is useful if your application could find that another application has already opened it with the same name. You could just use "Create" for even more simplicity.

Next, I generate an "Array of 26 bytes" called "bytes". This is going to be my byte memory buffer, which can hold anything I wish to share across the applications. In this case, I am just going to place a simple count into "Bytes" as 1,2,3,4... This is all done in the "For Next" loop.

Now we need to make our shared memory called "MemoryFile" viewable to our other applications. This is done by using an object I called "writer" and calling the method "CreatViewAccessor". This now makes the memory file data "Viewable". You can set the start and size that you wish your viewing application to see, I used 0 the Start of "bytes Array" and the "bytes Array" length (26).

Using writer = File.CreateViewAccessor(0, bytes.Length)

With the "MemoryFile" open and Viewable all that is left to do is to write our byte array to the shared memory this is done with:

writer.WriteArray(Of Byte)(0, bytes, 0, bytes.Length)

To read the data in shared memory you need to do the following.....

Call ReadMemoryMappedFile().

My object "File" here is used to "Open" an "Existing" shared memory file which we opened in the above method, called "MemoryFile".

Using file = MemoryMappedFile.OpenExisting("MemoryFile")

Here Try and Catch is important to help us, as the shared memory file may not exist, so I catch the exception and simply show a message box that it does not exist. You could add your own handler here. Note: unlike standard file handling, this class does not support "If.exist".

With the reader open, the class needs to know what you want to access and view. This is done with my object called "reader" and using the "CreateViewAccessor" method with the start and number of bytes to access. But first I ready a buffer to hold the data bytes to be read, I’ve also called it "bytes", because I know how many bytes I am sending - I've hard coded this the same size (26).

Then load the buffer with:

reader.ReadArray(Of Byte)(0, bytes, 0, bytes.Length)

Finally, I display the bytes converted to a string in a text box. Your code could parse the bytes for commands or data for further action or events. You should close the memory just like you would do with a file. In this example, I left it open so it can be called recursively for demonstration.

The code shown here is just one form; the same code is repeated in a different application I called form 2, with just the data in the write array changed to show that you can change it.

Using the Code

The demo VB.NET application is two projects in the same VS2010 solution. They consist of one form each. We use the System.IO.MemoryMappedFiles namespace in both and my example uses a few bytes from your system memory.

Application Form1 writes a few bytes when you click the Makefile button. E.g., values 1, 2, 3, 4.. etc. You can read them back on the same form textbox with the ReadFile button, or more importantly from the other application Form2 Readfile button.

Application Form2 Makefile button puts some different data (adds 10) to the same shared memory file so that you can see how easy it is to read the different values.

Once you play with the demo, you should be able to adapt it for your own applications.....

Imports System
Imports System.IO
Imports System.IO.MemoryMappedFiles

''' <summary>
''' Demo Form 1
''' </summary>
''' <remarks>
''' By David Rathbone 18/08/2011
''' Many thanks to Microsoft
''' </remarks>
Public Class Form1
    ''' <summary>
    ''' Write Memory
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub MakeMemoryMappedFile()

        Dim File = MemoryMappedFile.CreateOrOpen("MemoryFile", 26)
        Dim bytes = New Byte(25) {}
        For i As Integer = 0 To bytes.Length - 1
            bytes(i) = i + 1
        Next

        Using writer = File.CreateViewAccessor(0, bytes.Length)
            writer.WriteArray(Of Byte)(0, bytes, 0, bytes.Length)
        End Using
    End Sub

    ''' <summary>
    ''' Read Memory
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub ReadMemoryMappedFile()

        Try
            Using file = MemoryMappedFile.OpenExisting("MemoryFile")
                Using reader = file.CreateViewAccessor(0, 26)
                    Dim bytes = New Byte(25) {}
                    reader.ReadArray(Of Byte)(0, bytes, 0, bytes.Length)

                    TextBox1.Text = ""
                    For i As Integer = 0 To bytes.Length - 1
                        TextBox1.AppendText(CStr(bytes(i)) + " ")
                    Next

                End Using
            End Using
        Catch noFile As FileNotFoundException
 
            TextBox1.Text = "Memory-mapped file does not exist."
        Catch Ex As Exception
 
        End Try
    End Sub

    ''' <summary>
    ''' Button Make File Click event
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub Btn_Make_Click(sender As System.Object, e As System.EventArgs) _
        Handles Btn_Make.Click
        MakeMemoryMappedFile()
    End Sub

    ''' <summary>
    ''' Button Read File Click event
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub Btn_Read_Click(sender As System.Object, e As System.EventArgs) _
        Handles Btn_Read.Click
        ReadMemoryMappedFile()
    End Sub
End Class

History

  • First version: 18/08/2011.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here