Marshal Memory Map循环缓冲区问题

时间:2012-01-23 22:11:42

标签: memory marshalling shared circular-buffer

在过去的一个月里,我一直致力于共享内存/循环缓冲区实现。我使用了以下提供的MemMap类的基本概念:

http://www.codeproject.com/Articles/10797/Using-FileMapping-on-NET-as-IPC

但是我已经通过更多功能增强了它。这是我目标的快速解释:

  1. 创建共享内存以将数据写入循环缓冲区
  2. 从其他应用程序连接到共享内存以读取数据
  3. 当作者方面的某些重要数据参数发生变化时,请关闭地图并打开尺寸合适的新地图。 读者将收到有关此更改的通知,然后连接到新地图,并继续阅读。
  4. 问题出在作者重新初始化之后。读者连接完全正常,因为我保留了一个内存映射,以便传递新的地图名称。但是,一段时间后,读写器将遇到“尝试写入/读取受保护的内存异常”。更糟糕的是,这并不总是发生,如果新地图比以前的更大或更小也无关紧要。

    我正在使用互斥锁,循环缓冲区索引处理得很好。

    有相当多的代码要展示,如果你只是预感并且不想阅读它,那么我将非常感谢你的提示:D

    到目前为止,我的代码处于稍后的阶段,所以我只会展示可能的嫌疑人以避免混淆:

    将读者连接到现有地图:

    ''' <summary>
    ''' For connecting to existing memory map
    ''' </summary>
    ''' <param name="Name"></param>
    ''' <remarks></remarks>
    Public Sub New(ByVal Name As String)
        mapHandle = OpenFileMapping(PAGE_READONLY, 0, "Global/" + Name) 'Connect to pre-existing map
        If mapHandle = 0 Then
            Throw New System.Exception("FileMapping:" + Name + " error:" + GetLastError.ToString)
        End If
    
        mapName = "Global/" + Name
        mapAddress = MapViewOfFile(mapHandle, FileMapAccess.FILE_MAP_ALL_ACCESS, 0, 0, 0)
        If mapAddress = 0 Then
            CloseHandle(mapHandle)
            Throw New System.Exception("MapViewOfFile error:" + GetLastError.ToString)
        End If
        mapPointer = New IntPtr(mapAddress)
    End Sub
    

    创建一个WRITER:

       ''' <summary>
    ''' For creating new memory map
    ''' </summary>
    ''' <param name="Name">
    ''' Unique name to associate with map.
    ''' </param>
    ''' <param name="Size">
    ''' Total bytes to allocate for map.
    ''' </param>
    ''' <remarks></remarks>
    Public Sub New(ByVal Name As String, ByVal Size As Integer)
        mapHandle = CreateFileMapping(0, IntPtr.Zero, PAGE_READWRITE, 0, Size, "Global/" + Name)
        If mapHandle = 0 Then
            Throw New System.Exception("FileMapping:" + Name + " error:" + GetLastError.ToString)
        Else
    
            '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            'We need to connect if pre-existing memory map
            If GetLastError = ERROR_ALREADY_EXISTS Then
                IsNew = False          'Create accesible flag
                CloseHandle(mapHandle) 'Close the map we just created
                mapHandle = OpenFileMapping(PAGE_READONLY, 0, "Global/" + Name) 'Connect to pre-existing map
                If mapHandle = 0 Then
                    Throw New System.Exception("FileMapping:" + Name + " error:" + GetLastError.ToString)
                End If
            End If
            '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        End If
    
        '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        mapName = "Global/" + Name
        '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        mapSize = Size
        mapAddress = MapViewOfFile(mapHandle, FileMapAccess.FILE_MAP_ALL_ACCESS, 0, 0, 0) 'mod E.L.
        If mapAddress = 0 Then
            CloseHandle(mapHandle)
            Throw New System.Exception("MapViewOfFile error:" + GetLastError.ToString)
        End If
        mapPointer = New IntPtr(mapAddress)
    End Sub
    

    将双打写入记忆:

    Public Sub writeDoubles(ByVal offset As Integer, ByVal values_ As Double(), Optional ByVal startIdx As Integer = 0, Optional ByVal length As Integer = 0)
        If length = 0 Then length = values_.Length
        Marshal.Copy(values_, startIdx, New IntPtr(mapPointer.ToInt32 + offset), length)
    

    阅读双打:

       Public Sub readDoubles(ByVal offset As Integer, ByRef destArray() As Double, ByVal length As Integer, Optional ByVal startIndex As Integer = -1)
        If startIndex < 0 Then startIndex = 0
        Marshal.Copy(New IntPtr(mapPointer.ToInt32 + offset), destArray, startIndex, length)
    End Sub
    

    确定性内存清理:

       Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
        ' Check to see if Dispose has already been called.
        If Not Me.disposed Then
            ' If disposing equals true, dispose all managed 
            ' and unmanaged resources.
            If disposing Then
                ' Dispose managed resources
            End If
    
            Dim closeHandleResult As Integer
            Dim unmapResult As Boolean
            'Clean up unmanaged resources here.
            closeHandleResult = CloseHandle(mapHandle)  'Successful = 1 
            unmapResult = UnmapViewOfFile(mapPointer)   'Successful = true
    
            If closeHandleResult = 1 And unmapResult Then
                'Reinitialize map pointer if memory deallocation was successful
                mapPointer = IntPtr.Zero
                'Note disposing has completed, only gets set 
                'if memory deallocation was successful
                disposed = True
            End If
        End If 'Not Me.disposed
    End Sub
    

0 个答案:

没有答案
相关问题