Sto provando a costruire un sistema di calcolo distributivo che utilizza i file di mappatura della memoria per coordinare il lavoro tra diversi PC in rete tramite VBA. In altre parole, voglio che un gruppo di computer in rete esegua il lavoro contemporaneamente in modo coordinato su un singolo progetto che può essere facilmente diviso in parti diverse. Un PC impiega più di 13 ore per completare il progetto, il che non è pratico per il mio cliente.Come archiviare i dati e recuperare i dati dai file di mappatura della memoria utilizzando CopyMemory in VBA?
Desidero memorizzare le informazioni nei file di mappatura della memoria che aiuteranno i PC a lavorare sul progetto in modo coordinato (cioè senza duplicazioni di lavoro, evitare problemi di razza, ecc.). Ho provato ad usare altri tipi di file per realizzare questo e causa problemi di file race o ci vuole troppo tempo. Quindi, come suggerito su questo forum, sto provando i file di mappatura della memoria.
Sono nuovo di zecca per i file di mappatura della memoria e il calcolo distributivo. Deve essere fatto in VBA. Per quanto ne so, devo specificare che il file deve essere salvato su una directory sulla nostra rete (qui l'unità Z) a cui tutti i PC hanno accesso. Ho messo insieme un po 'di codice da vari luoghi:
Option Explicit
Private Const PAGE_READWRITE As Long = &H4
Private Const FILE_MAP_WRITE As Long = &H2
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const OPEN_ALWAYS = 4
Private Const FILE_ATTRIBUTE_NORMAL = &H80
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, _
ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, _
ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, _
ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CreateFileMapping Lib "kernel32.dll" Alias "CreateFileMappingA" (_
ByVal hFile As Long, _
ByVal lpFileMappigAttributes As Long, _
ByVal flProtect As Long, _
ByVal dwMaximumSizeHigh As Long, _
ByVal dwMaximumSizeLow As Long, _
ByVal lpName As String) As Long
Private Declare Function MapViewOfFile Lib "kernel32.dll" (_
ByVal hFileMappingObject As Long, _
ByVal dwDesiredAccess As Long, _
ByVal dwFileOffsetHigh As Long, _
ByVal dwFileOffsetLow As Long, _
ByVal dwNumberOfBytesToMap As Long) As Long
#If VBA7 Then
Public Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (destination As Any, source As Any, _
ByVal length As Long)
#Else
Public Declare Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (destination As Any, source As Any, _
ByVal length As Long)
#End If
Private Declare Function UnmapViewOfFile Lib "kernel32.dll" (_
ByRef lpBaseAddress As Any) As Long
Private Declare Function CloseHandle Lib "kernel32.dll" (_
ByVal hObject As Long) As Long
Private hMMF As Long
Private pMemFile As Long
Sub IntoMemoryFileOutOfMemoryFile()
Dim sFile As String
Dim hFile As Long
sFile = "Z:\path\test1.txt"
hFile = CreateFile(sFile, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
hMMF = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, 1000000, "MyMemoryMappedFile")
pMemFile = MapViewOfFile(hMMF, FILE_MAP_WRITE, 0, 0, 0)
Dim buffer As String
buffer = "testing1"
CopyMemory pMemFile, ByVal buffer, 128
hMMF = CreateFileMapping(-1, 0, PAGE_READWRITE, 0, 1000000, "MyMemoryMappedFile")
pMemFile = MapViewOfFile(hMMF, FILE_MAP_WRITE, 0, 0, 0)
Dim buffer2 As String
buffer2 = String$(128, vbNullChar)
CopyMemory ByVal buffer2, pMemFile, 128
MsgBox buffer2 & " < - it worked?"
UnmapViewOfFile pMemFile
CloseHandle hMMF
End Sub
Come un piccolo esempio, il codice di cui sopra cerca di mettere la stringa "testing1" nel file test1.txt quindi recuperare quella stringa e memorizzarlo in buffer2 variabile e, infine, mostra quella stringa tramite un msgbox. Super semplice. Tuttavia, non ho idea di cosa sto facendo.
Tutti i nostri PC sono a 64 bit, Windows 7, Office/Excel 2013.
Problemi/domande:
- MsgBox è vuoto quando si esegue IntoMemoryFileOutOfMemoryFile
- Dopo che il sub è completa I apri test1.txt e ottengo: "Il processo non può accedere al file perché è utilizzato da un altro processo." Il che mi dice che non sto usando UnmapViewOfFile e/o CloseHandle correttamente.
- Mi piacerebbe rendere persistenti questi file di memoria, quindi se tutti i PC sono interrotti posso riavviare il processo e riprendere da dove ho lasciato.
Ecco alcuni dei link che ho usato per arrivare dove sono ora:
https://msdn.microsoft.com/en-us/library/dd997372%28v=vs.110%29.aspx
http://vb.mvps.org/hardcore/html/sharedmemorythroughmemory-mappedfiles.htm
http://www.tushar-mehta.com/publish_train/xl_vba_cases/1016%20Office%202010%20VBA.shtml
Informazioni interessanti ma non importanti: Il "progetto" è per un cliente di hedge fund. Sono un ragazzo delle finanze diventato fondamentale. Stiamo analizzando oltre 2000 azioni più su base giornaliera oltre 1250 campi dati per fare segnali/previsioni macroeconomici per comprare e vendere azioni, futures e opzioni.
UPDATE: Se cambio le due linee CopyMemory come questa (passare pMemFile per valore) rispettivamente:
CopyMemory ByVal pMemFile, buffer, 128
e ...
CopyMemory buffer2, ByVal pMemFile, 128
Ottengo un sacco di personaggi pazzi nel file test1.txt ed Excel si blocca.
Perché questo deve essere VBA? Per quanto ami VBA, sembra un po 'come usare un martello quando quello che ti serve è un cacciavite. – RubberDuck
@RubberDuck Potrebbero essere i requisiti del cliente (ho avuto lo stesso problema per uno strumento molto più semplice) che hanno qualcuno che è in grado di mantenere in VBA ma non in altre lingue. Passa inosservato, ma interessante, ci penserò, ma non posso fare promesse! ;) – R3uK
@RubberDuck - Non è la mia scelta neanche. – mountainclimber