Introduction

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

You have an application, 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? 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 applications "A" thread will have no knowledge of applications "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’s doesn’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" e.g.

       Using file = MemoryMappedFile.OpenExisting("MemoryFile")

Here the Try and Catch is important to help us, as the shared memory file may not exist, so I catch the exception and simply show in 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 do you want to access and view. This is done with my object called "reader" and using"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 was 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 actions 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. It consists of one form each. It uses 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 Make file button puts some different data (Adds 10) to the same shared memory file so that you can see how easy it was to read the different values.

Once you play with the demo you should be able to adapt 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

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"