在过去的一个月里,我一直致力于共享内存/循环缓冲区实现。我使用了以下提供的MemMap类的基本概念:
http://www.codeproject.com/Articles/10797/Using-FileMapping-on-NET-as-IPC
但是我已经通过更多功能增强了它。这是我目标的快速解释:
问题出在作者重新初始化之后。读者连接完全正常,因为我保留了一个内存映射,以便传递新的地图名称。但是,一段时间后,读写器将遇到“尝试写入/读取受保护的内存异常”。更糟糕的是,这并不总是发生,如果新地图比以前的更大或更小也无关紧要。
我正在使用互斥锁,循环缓冲区索引处理得很好。
有相当多的代码要展示,如果你只是预感并且不想阅读它,那么我将非常感谢你的提示: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