我正在尝试构建一个分布式计算系统,使用内存映射文件在多台网络PC之间协调工作,所有操作都通过VBA进行。换句话说,我想让一组网络计算机在同一时间协调完成单个项目的工作,该项目可以轻松地分成不同的部分。其中一台PC需要13个小时以上才能完成该项目,这对我的客户来说是不切实际的。
我希望将信息存储在内存映射文件中,以帮助PC协调完成项目(即避免重复工作、避免竞争问题等)。我已经尝试使用其他类型的文件来实现这一点,但会导致文件竞争问题或者耗时过长。因此,如此论坛上建议的,我正在尝试使用内存映射文件。
我对内存映射文件和分布式计算都很陌生,必须在VBA中完成。据我所知,我必须指定文件保存在我们网络上的目录(这里是Z驱动器),所有PC都可以访问。我从各种地方拼凑了一些代码:
作为一个小例子,上面的代码尝试将字符串“testing1”放入文件test1.txt中,然后检索该字符串并将其存储在变量buffer2中,最后通过msgbox显示该字符串。非常简单。但是,我不知道我在做什么。
我们所有的电脑都是64位的,Windows 7,Office/Excel 2013。
问题/疑问:
我希望将信息存储在内存映射文件中,以帮助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
作为一个小例子,上面的代码尝试将字符串“testing1”放入文件test1.txt中,然后检索该字符串并将其存储在变量buffer2中,最后通过msgbox显示该字符串。非常简单。但是,我不知道我在做什么。
我们所有的电脑都是64位的,Windows 7,Office/Excel 2013。
问题/疑问:
- 当我运行IntoMemoryFileOutOfMemoryFile时,msgbox为空白。
- 在子程序完成后,我打开test1.txt并得到:“由于正在被另一个进程使用,因此无法访问该文件。”这告诉我我没有正确使用UnmapViewOfFile和/或CloseHandle。
- 我想使这些内存文件持久化,以便如果所有计算机中断,我可以重新启动进程并从上次离开的地方继续。
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
有趣但不重要的信息:这个“项目”是为一个对冲基金客户而做的。我是一名金融人员转型为基本量化分析师。我们每天分析2000多只股票和1250多个数据字段,以制定宏观经济信号/预测来买卖股票、期货和期权。
更新:如果我将两个CopyMemory行改成这样(通过值传递pMemFile),则:
CopyMemory ByVal pMemFile, buffer, 128
和……
CopyMemory buffer2, ByVal pMemFile, 128
我在文件test1.txt中得到了一堆奇怪的字符,导致Excel崩溃。