В течение последнего месяца я работал над реализацией общей памяти / циклического буфера.Я использовал основные понятия класса 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
Для создания ПИСАТЕЛЯ:
''' <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