虽然我的问题可能是noob-ish,让我解释一下: 我最近开始玩MMF,创建2个进程,访问相同的内存指针,Process1写一个整数到MMF,Process2有一个按钮,onClick,它显示MMF中的第一个整数。
我想要做的是,当我发送"时,将数据从Process1写入MMF,Process2通知此请求,并显示准确时间的数据,依此类推,写入新数据。
我不确定线程检查MMF中的更改是否正常,听起来很脏。
希望有人可以指出我的解决方案,因为我没有想法:(。
这是一段代码:
procedure OpenMap;
var
llInit: Boolean;
lInt: Integer;
begin
if Hmapping<>0 then Exit;
HMapping := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE,
0, MAPFILESIZE, pchar('wowsniff'));
// Check if already exists
llInit := (GetLastError() <> ERROR_ALREADY_EXISTS);
if (hMapping = 0) then
exit;
PMapData := MapViewOfFile(HMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if PMapData = nil then
exit;
if (llInit) then
begin
// Init block to #0 if newly created
FillChar(PMapData^, MAPFILESIZE, 0);
end
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
LockMap;
PDword(PMapData)^:=Strtoint(edit1.Text);
UnlockMap;
end;
答案 0 :(得分:3)
通过TEvent
或CreateEvent()
使用命名的事件对象。两个进程都可以创建相同的事件名称(就像创建相同的映射名称一样),然后进程1可以在写入新数据时发出事件信号,进程2可以在读取数据之前等待事件发出信号(对于实时阅读,你应该使用一个线程进行等待/阅读。
您可以通过TMutex
或CreateMutex()
使用命名的互斥锁对象,在读取/写入数据时实现锁定/解锁功能。
尝试这样的事情:
流程1:
procedure OpenMap;
var
llInit: Boolean;
begin
llInit := False;
if hMapEvent = 0 then
begin
hMapEvent := CreateEvent(nil, True, False, PChar('wowsniffDataReady'));
if hMapEvent = 0 then RaiseLastOSError;
end;
if hMapLock = 0 then
begin
hMapLock := CreateMutex(nil, False, PChar('wowsniffDataLock'));
if hMapLock = 0 then RaiseLastOSError;
end;
if hMapping = 0 then
begin
hMapping := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, MAPFILESIZE, PChar('wowsniff'));
if hMapping = 0 then RaiseLastOSError;
// Check if already exists
llInit := (GetLastError() <> ERROR_ALREADY_EXISTS);
end;
if PMapData = nil then
begin
PMapData := MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, MAPFILESIZE);
if PMapData = nil then RaiseLastOSError;
if llInit then
begin
// Init block to #0 if newly created
ZeroMemory(PMapData, MAPFILESIZE);
end;
end;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
LockMap;
try
PDword(PMapData)^ := StrToInt(Edit1.Text);
SetEvent(hMapEvent);
finally
UnlockMap;
end;
end;
procedure TForm1.LockMap;
var
llRet: DWORD;
begin
llRet := WaitForSingleObject(hMapLock, 5000);
if llRet = WAIT_OBJECT_0 then Exit;
if llRet <> WAIT_FAILED then SetLastError(llRet);
RaiseLastOSError;
end;
procedure TForm1.UnlockMap;
begin
ReleaseMutex(hMapLock);
end;
流程2:
type
TMyThread = class(TThread)
private
hTerminate: THandle;
hMapLock: THandle;
hMapEvent: THandle;
hMapping: THandle;
PMapData: Pointer;
protected
procedure Execute; override;
procedure DoTerminate; override;
procedure TerminatedSet; override;
public
constructor Create;
destructor Destroy; override;
end;
constructor TMyThread.Create;
begin
inherited Create(False);
hTerminate := CreateEvent(nil, True, False, nil);
if hTerminate = 0 then RaiseLastOSError;
end;
destructor TMyThread.Destroy;
begin
if hTerminate <> 0 then CloseHandle(hTerminate)
end;
procedure TMyThread.TerminatedSet;
begin
SetEvent(hTerminate);
end;
procedure TMyThread.Execute;
var
llInit: Boolean;
llRet, llValue: DWORD;
llHandles: array[0..1] of THandle;
begin
hMapEvent := CreateEvent(nil, True, False, PChar('wowsniffDataReady'));
if hMapEvent = 0 then RaiseLastOSError;
hMapLock := CreateMutex(nil, False, PChar('wowsniffDataLock'));
if hMapLock = 0 then RaiseLastOSError;
hMapping := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, MAPFILESIZE, PChar('wowsniff'));
if hMapping = 0 then RaiseLastOSError;
// Check if already exists
llInit := (GetLastError() <> ERROR_ALREADY_EXISTS);
PMapData := MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, MAPFILESIZE);
if PMapData = nil then RaiseLastOSError;
if llInit then
begin
// Init block to #0 if newly created
FillChar(PMapData^, MAPFILESIZE, 0);
end;
llHandles[0] := hMapEvent;
llHandles[1] := hTerminate;
while not Terminated do
begin
llRet := WaitForMultipleObjects(2, PWOHandleArray(@llHandles), False, INFINITE);
case llRet of
WAIT_OBJECT_0+0:
begin
llRet := WaitForSingleObject(hMapLock, 5000);
if llRet = WAIT_OBJECT_0 then
begin
try
llValue := PDword(PMapData)^;
ResetEvent(hMapEvent);
finally
ReleaseMutex(hMapLock);
end;
// use llValue as needed...
Continue;
end;
end;
WAIT_OBJECT_0+1:
begin
Exit;
end;
end;
if llRet <> WAIT_FAILED then SetLastError(llRet);
RaiseLastOSError;
end;
end;
procedure TMyThread.DoTerminate;
begin
if PMapData <> nil then UnmapViewOfFile(PMapData);
if hMapping <> 0 then CloseHandle(hMapping);
if hMapEvent <> 0 then CloseHandle(hMapEvent);
if hMapLock <> 0 then CloseHandle(hMapLock);
inherited;
end;