Gunnar Peipman's ASP.NET blog

ASP.NET, C#, SharePoint, SQL Server and general software development topics.

Sponsors

News

 
 
 
 
 
Programming Blogs - Blog Catalog Blog Directory
 
 
 

Links

Social

.Net Framework 4.0: Using memory mapped files

.Net Framework 4.0 introduces memory mapped files. Memory mapped files are useful when you need to do in-memory data manipulation and your data structures are large. For large in-memory data the performance of memory mapped file is the best. It is much faster than MemoryStream. And like files on hard disc, memory mapped files can be shared between different programs. MemoryMappedFile and other classes for memory mapped files can be found from System.IO.MemoryMappedFiles namespace.

Now let’s see the example that contains two applications: one of them is primitive server that creates and holds memory mapped file and the other is simple client that reads that file. In the end of the posting you can find download link for example Visual Studio 2010 solution.

MemoryMappedFile server

Our server, as I said before, is primitive. It creates memory mapped file and writes some bytes to our file. Then it starts waiting key press from user to release resources and exit. The code of server is here.

C#
static void Main(string[] args)
{
    Console.WriteLine("Memory mapped file server started");
 
    using (var file = MemoryMappedFile.CreateNew("myFile", int.MaxValue))
    {
        var bytes = new byte[24];
        for (var i = 0; i < bytes.Length; i++)
            bytes[i] = (byte)(65 + i);
 
        using (var writer = file.CreateViewAccessor(0, bytes.Length))
        {
            writer.WriteArray<byte>(0, bytes, 0, bytes.Length);
        }
        Console.WriteLine("Run memory mapped file reader before exit");
        Console.WriteLine("Press any key to exit ...");
        Console.ReadLine();
    }
}

VB.NET
Private Shared Sub Main(ByVal args As String())
    Console.WriteLine("Memory mapped file server started")
    
    Using file = MemoryMappedFile.CreateNew("myFile", Integer.MaxValue)
        Dim bytes = New Byte(23) {}
        For i = 0 To bytes.Length - 1
            bytes(i) = CByte((65 + i))
        Next
        
        Using writer = file.CreateViewAccessor(0, bytes.Length)
            writer.WriteArray(Of Byte)(0, bytes, 0, bytes.Length)
        End Using
        Console.WriteLine("Before exiting run memory mapped file reader")
        Console.WriteLine("Press any key to exit ...")
        Console.ReadLine()
    End Using
End Sub

MemoryMappedFile reader

The client project opens memory mapped file and reads bytes that server wrote there. I hope you notice that I hard coded the count of bytes that reader reads from memory mapped file. The point is simple – we are accessing memory mapped file directly without any contracts for file structure. In reality there will be some API that you use to manager memory mapped file in your application.

C#

static void Main(string[] args)
{
    Console.WriteLine("Memory mapped file reader started");
 
    using (var file = MemoryMappedFile.OpenExisting("myFile"))
    {
        using (var reader = file.CreateViewAccessor(0, 24))
        {
            var bytes = new byte[24];
            reader.ReadArray<byte>(0, bytes, 0, bytes.Length);
 
            Console.WriteLine("Reading bytes");
            for (var i = 0; i < bytes.Length; i++)
                Console.Write((char)bytes[i] + " ");
 
            Console.WriteLine(string.Empty);
        }
    }
 
    Console.WriteLine("Press any key to exit ...");
    Console.ReadLine();
}

VB.NET
Private Shared Sub Main(ByVal args As String())
    Console.WriteLine("Memory mapped file reader started")
    
    Using file = MemoryMappedFile.OpenExisting("myFile")
        Using reader = file.CreateViewAccessor(0, 24)
            Dim bytes = New Byte(23) {}
            reader.ReadArray(Of Byte)(0, bytes, 0, bytes.Length)
            
            Console.WriteLine("Reading bytes")
            For i = 0 To bytes.Length - 1
                Console.Write(CChar(bytes(i)) & " ")
            Next
            
            Console.WriteLine(String.Empty)
        End Using
    End Using
    
    Console.WriteLine("Press any key to exit ...")
    Console.ReadLine()
End Sub

Now run server (MemoryMappedFileCreate) and after that the client (MemoryMappedFileRead). Server creates new memory mapped file and writes there 24 bytes of characters. Client then reads these bytes and writes them to console.

To find out more about memory mapped files feel free to read MSDN Utopia blog entry Working with memory mapped files in .NET 4.

MemoryMappedFiles.zip
Visual Studio 2010 Solution
Size: 25 KB

kick it on DotNetKicks.com pimp it Progg it Shout it

Comments

Visual Studio 2010 and .Net Framework 4.0 - Gunnar Peipman's ASP.NET blog said:

Pingback from  Visual Studio 2010 and .Net Framework 4.0 - Gunnar Peipman's ASP.NET blog

# June 21, 2009 5:59 AM

DotNetShoutout said:

Thank you for submitting this cool story - Trackback from DotNetShoutout

# June 21, 2009 6:02 AM

DotNetBurner - Visual Studio said:

DotNetBurner - burning hot .net content

# June 21, 2009 6:03 AM

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# June 21, 2009 6:05 AM

progg.ru said:

Thank you for submitting this cool story - Trackback from progg.ru

# June 21, 2009 6:08 AM

Jonas Elfström said:

I see that you set the capacity to int.MaxValue / 2147483647 bytes. That is quite a chunk of memory on a 32-bit system. Do you know if MemoryMappedFile.CreateNew needs to find 2GB of continuous free memory to succeed if you specify int.MaxValue?

According to msdn.microsoft.com/.../dd267529%28VS.100%29.aspx capacity is a Int64. You didn't happen to test to "allocate" more than 2GB in 32-bit Windows?

# June 23, 2009 5:27 AM

Cameron said:

Do you know if I can try these examples on VS2008,

I have installed the Net framework 4 beta 1.

Thank you

# June 24, 2009 11:13 AM

DigiMortal said:

Thanks for comments, guys! :)

Aaron: I made no tests with different boundary values. Also I made no tests in 64bit environment.

Cameron: AFAIK you cannot use .Net Framework 4 Beta 1 features in VS2008.

# July 3, 2009 3:20 AM

Bill Jenkins said:

Console based examples worked great. If I put inside a windows form, the client works fine, but the server doesn't. Am I missing something here? I used the VB code provided but wrapped in a form.

# August 5, 2009 4:37 PM

DigiMortal said:

Hello Bill!

Did your VB client worked okay against console based server?

# August 5, 2009 4:55 PM

Bill Jenkins said:

Thanks for responding.

Yes, both versions of the VB client (console-based and windows-based) worked, but only for the console-based server. Both failed with a "cannot find file" exception when I used the windows-based server.

# August 5, 2009 8:02 PM

DigiMortal said:

I was not able to find a reason for this behavior. Did you try to run both of them under same privileges? Did you try to run them under admin privileges?

# August 6, 2009 1:53 AM

Bill Jenkins said:

Thanks for asking. All were run under the same privileges. Here is the code:

Imports System.IO.MemoryMappedFiles

       Using file = MemoryMappedFile.CreateNew("myFile", Integer.MaxValue)

           Dim bytes = New Byte(23) {}

           For i = 0 To bytes.Length - 1

               bytes(i) = CByte(i + 65)

           Next

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

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

           End Using

       End Using

# August 6, 2009 12:19 PM

Bill Jenkins said:

Also, I have Admin privilege on my computer (XP-32) and run my programs in that mode.

# August 6, 2009 3:04 PM

DigiMortal said:

Hmm... seems like I have to handle this problem over to .Net development team.

# August 6, 2009 5:14 PM

Bill Jenkins said:

Thanks, DigiMortal. I hope it's not me. Good luck!

# August 6, 2009 7:43 PM

DigiMortal said:

Heh, good joke! :)

Bill, I reported this problem to Connect. You can find it here: connect.microsoft.com/.../ViewFeedback.aspx

If you have more details to give then feel free to drop me a line. Also you can keep your eye on this Connect ticket to see if there is solution to your problem.

# August 7, 2009 1:21 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)