Click here to Skip to main content
15,885,537 members
Articles / Web Development / ASP.NET

Using Memory Mapped Files in ASP.NET using VB.NET

Rate me:
Please Sign up or sign in to vote.
4.85/5 (20 votes)
22 Dec 200512 min read 213.4K   1.9K   94  
MemoryMappedCache is a small project can be used to host a proactive loaded cache using a Windows Service.
Imports System.Runtime.InteropServices

' ------------------------------------------------------------------------------
' The .NET Framework has a Mutex-class built-in under System.Threading.Mutex.
' The problem with mutexes created with this class is that these mutexes are
' using the default security. Because of this, gui- or console-appications
' don't have sufficient access to open a mutex created in a service running
' under the Local System Account.
'
' To work-around this limitation, I've created my own Mutex-class which doesn't
' create mutexes using default security.
'
' For more information about this problem and a more detailed explanation of
' the work-around, read Ask Dr. GUI #49:
' http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaskdr/html/drgui49.asp
' ------------------------------------------------------------------------------

Friend NotInheritable Class Mutex
  Implements IDisposable

  Private mMutex As Integer = 0
  Private mName As String = ""

  Public Sub New(ByVal lcName As String)
    mName = lcName
  End Sub

  Private Sub Create()
    Dim objSidEveryone As IntPtr = IntPtr.Zero

    ' First we're going to create a NULL DACL. An object with NULL-DACL security grants all 
    ' access to everyone, regardless of security context. One downside of this approach is 
    ' that the object is now completely unsecured. This should be reprogrammed in a safer way!
    ' TODO Develop without using a NULL DACL. More information can be found in MSDN in 
    ' Ask Dr. GUI #49.
    Dim objSecurityDescriptor As ApiHelper.SECURITY_DESCRIPTOR
    Dim intResult As Integer = ApiHelper.InitializeSecurityDescriptor(objSecurityDescriptor, ApiHelper.SECURITY_DESCRIPTOR_REVISION)
    If intResult = 0 Then
      Throw New Exception("InitializeSecurityDescriptor failed: " & ApiHelper.GetWin32ErrorMessage(Marshal.GetLastWin32Error))
    End If

    intResult = ApiHelper.SetSecurityDescriptorDacl(objSecurityDescriptor, 1, New IntPtr(0), 0)
    If intResult = 0 Then
      Throw New Exception("SetSecurityDescriptorDacl failed: " & ApiHelper.GetWin32ErrorMessage(Marshal.GetLastWin32Error))
    End If

    Dim objSecurityAttributes As ApiHelper.SECURITY_ATTRIBUTES
    objSecurityAttributes = New ApiHelper.SECURITY_ATTRIBUTES
    objSecurityAttributes.nLength = Marshal.SizeOf(objSecurityAttributes)
    objSecurityAttributes.bInheritHandle = 0
    objSecurityAttributes.lpSecurityDescriptor = ApiHelper.VarPtr(objSecurityDescriptor)

    mMutex = ApiHelper.CreateMutex(objSecurityAttributes, 0, mName)
    If mMutex = 0 Then
      Throw New Exception("CreateMutex failed: " & Marshal.GetLastWin32Error.ToString)
    End If
  End Sub

  Public Sub Wait()
    Dim intResult As Integer

    ' The following document gives more information about the mutex-workflow
    ' ms-help://MS.VSCC.2003/MS.MSDNQTR.2004APR.1033/dllproc/base/using_mutex_objects.htm

    ' Create a mutex with no initial owner.
    Call Create()

    ' Request ownership of Mutex
    intResult = ApiHelper.WaitForSingleObject(mMutex, ApiHelper.INFINITE)

    Select Case intResult
      Case ApiHelper.WAIT_OBJECT_0
        ' the thread got mutex ownership...
        Exit Sub

      Case ApiHelper.WAIT_TIMEOUT
        ' cannot get mutex ownership due to time-out
        Throw New Exception("Timed out waiting for mutex-ownership.")

      Case ApiHelper.WAIT_ABANDONED
        ' The specified object is a mutex object that was not released 
        ' by the thread that owned the mutex object before the owning thread 
        ' terminated. Ownership of the mutex object is granted to the calling 
        ' thread, and the mutex is set to nonsignaled.
        Throw New Exception("WAIT_ABANDONED returned by WaitForSingleObject")

      Case Else
        Throw New Exception("Unexpected result returned by WaitForSingleObject")

    End Select
  End Sub

  Public Sub Release()
    If mMutex <> 0 Then
      If ApiHelper.ReleaseMutex(mMutex) = 0 Then
        Throw New Exception("ReleaseMutex failed: " & Marshal.GetLastWin32Error.ToString)
      End If
      mMutex = 0
    End If
  End Sub

  Protected Overrides Sub Finalize()
    Dispose(False)
  End Sub

  Private Sub Dispose(ByVal lcDisposing As Boolean)
    SyncLock Me
      If mMutex <> 0 Then
        Call ApiHelper.CloseHandle(New IntPtr(mMutex))
        mMutex = 0
      End If
    End SyncLock
  End Sub

  Public Sub Dispose() Implements System.IDisposable.Dispose
    ' Because the object is explicitely cleaned up, stop the garbage
    ' collector from caling the Finalize-method.
    GC.SuppressFinalize(Me)

    ' Cleaning up...
    Dispose(True)
  End Sub

  ' Personally, I find it more logical to Close a Mutex than to Dispose it. So users
  ' can call Close if they want to.
  Public Sub Close()
    Call Dispose()
  End Sub
End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

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


Written By
Team Leader
Belgium Belgium
I am a developer spending most of my time in C#, .NET 2.0 and Sql Server 2005. I am working for a Belgium company called Adam Software developing Asset Management Software. More information about my company and our software can be found at http://www.adamsoftware.net

Comments and Discussions