我正在嘗試構建一個分佈式計算系統,它使用內存映射文件通過VBA協調多臺聯網的PC之間的工作。換句話說,我想讓一組網絡計算機同時以協調的方式在單個項目上工作,這個項目可以很容易地劃分爲不同的部分。一臺PC需要13個小時才能完成該項目,這對我的客戶來說並不實際。如何使用VBA中的CopyMemory存儲數據並從內存映射文件中獲取數據?
我想將信息存儲在內存映射文件中,這將有助於PC以協調的方式處理項目(即不會重複工作,避免種族問題等)。我試過使用其他類型的文件來實現這一點,它會導致文件競爭問題或它需要很長時間。所以,正如這個論壇上的建議,我正在嘗試內存映射文件。
我是全新的內存映射文件和分佈式計算。必須在VBA中完成。據我所知,我必須指定將文件保存在我們網絡上的一個目錄(Z驅動器),以便所有PC都可以訪問。我曾經拼湊來自不同地方的一些代碼:
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
作爲一個小例子上面的代碼試圖把在文件test1.txt的字符串「testing1」然後檢索該字符串,並將其存儲在可變緩衝器2和最後通過msgbox顯示該字符串。超級簡單。但是,我不知道我在做什麼。
我們的電腦全部是64位的Windows 7,辦公/ Excel的2013年
問題/疑問:
- 的MSGBOX是空白的,當我運行IntoMemoryFileOutOfMemoryFile
- 子完成後,我打開test1.txt,我得到:「進程無法訪問文件,因爲它正在被另一個進程使用。」這告訴我我沒有正確使用UnmapViewOfFile和/或CloseHandle。
- 我想讓這些內存文件保持不變,所以如果所有的PC都被中斷,我可以重新啓動進程並在我離開的地方取回。
下面是一些我用的鏈接來獲得現在的我:
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
有趣但並不重要的信息:「項目」是針對對衝基金客戶的。我是一個走向根本定量的金融傢伙。我們每日分析超過1250多個數據領域的2000多隻股票,以制定宏觀經濟信號/預測以購買和出售股票,期貨和期權。
更新:如果我改變兩個CopyMemory的線像這樣分別(通過pMemFile由值):
CopyMemory ByVal pMemFile, buffer, 128
和...
CopyMemory buffer2, ByVal pMemFile, 128
我在文件test1.txt和excel崩潰中得到了一堆瘋狂的字符。
爲什麼這必須是VBA?就像我喜歡VBA一樣,當你真正需要的是螺絲刀時,它就像使用錘子一樣。 – RubberDuck
@RubberDuck可能是客戶的要求(我得到了一個更簡單的工具相同的問題),有一個人能夠維護在VBA,但沒有在其他語言。項目的方式在我的頭上,但有趣的是,我會研究它,但不能做出任何承諾! ;) – R3uK
@RubberDuck - 不是我的選擇。 – mountainclimber