首页 > 系统相关 >Delphi 多进程共享内存的简单封装单元

Delphi 多进程共享内存的简单封装单元

时间:2022-09-24 18:24:31浏览次数:81  
标签:begin end Delphi TShareMemStream ACCESS ms 封装 sa 共享内存

该单元转自武稀松的博客
稍作修改,使其支持Delphi7

{
共享内存封装.
封装成了MemoryStream的形式.
用法如下:
  var
    ms : TShareMemStream;
  ms := TShareMemStream.Create('Global\test', FILE_MAP_ALL_ACCESS, 4096);
  if (ms.Memory <> nil)(*and(ms.AlreadyExists)*) then
  //如果创建失败Memory指针是空指针
  //AlreadyExists表示已经存在了,也就是之前被别人(也许是别的进程)创建过了.
  begin
    //获取锁,多个进程线程访问安全访问
    if ms.GetLock(INFINITE) then
    begin
      ms.read(...);
      ms.write(...);
      //释放锁
      ms.ReleaseLock();
    end;
  end;
  ms.free;
}
unit ShareMemoryStream;

interface

uses
  SysUtils, Classes, Syncobjs, Windows;

type
  TShareMemStream = class(TCustomMemoryStream)
  private
    FFile: THandle;
    FSize: Int64;
    FEvent: TEvent;
    FAlreadyExists: Boolean;
  protected
    property Event: TEvent read FEvent;
  public
    constructor Create(const ShareName: string; ACCESS: DWORD = FILE_MAP_ALL_ACCESS; ASize: Int64 = 16 * 1024 * 1024);
    destructor Destroy; override;

    function Write(const Buffer; Count: Integer): Longint; override;

    function GetLock(ATimeOut: DWORD = INFINITE): Boolean;
    procedure ReleaseLock();

    property AlreadyExists: Boolean read FAlreadyExists;
  end;

implementation

procedure InitSecAttr(var sa: TSecurityAttributes; var sd: TSecurityDescriptor);
begin
  sa.nLength := sizeOf(sa);
  sa.lpSecurityDescriptor := @sd;
  sa.bInheritHandle := false;
  InitializeSecurityDescriptor(@sd, SECURITY_DESCRIPTOR_REVISION);
  SetSecurityDescriptorDacl(@sd, true, nil, false);
end;
 
{ TShareMem }

constructor TShareMemStream.Create(const ShareName: string; ACCESS: DWORD; ASize: Int64);
var
  sa: TSecurityAttributes;
  sd: TSecurityDescriptor;
  lprotect: DWORD;
  e: Integer;
begin
  FEvent := TEvent.Create(nil, false, true, ShareName + '_TShareMemStream_Event');
  FSize := ASize;
  InitSecAttr(sa, sd);

  ACCESS := ACCESS and (not SECTION_MAP_EXECUTE);

  if (ACCESS and FILE_MAP_WRITE) = FILE_MAP_WRITE then
    lprotect := PAGE_READWRITE
  else if (ACCESS and FILE_MAP_READ) = FILE_MAP_READ then
    lprotect := PAGE_READONLY;

  FFile := CreateFileMapping(INVALID_HANDLE_VALUE, @sa, lprotect, Int64Rec(FSize).Hi, Int64Rec(FSize).Lo, PChar(ShareName));
  e := GetLastError;
  MessageBox(0,PChar(IntToStr(e)),0,0);
  if FFile = 0 then
    Exit;
  FAlreadyExists := e = ERROR_ALREADY_EXISTS;
  SetPointer(MapViewOfFile(FFile, ACCESS, 0, 0, Int64Rec(FSize).Lo), Int64Rec(FSize).Lo);
end;

destructor TShareMemStream.Destroy;
begin
  if Memory <> nil then
  begin
    UnmapViewOfFile(Memory);
    SetPointer(nil, 0);
    Position := 0;
  end;
  if FFile <> 0 then
  begin
    CloseHandle(FFile);
    FFile := 0;
  end;
  FEvent.Free;
  inherited Destroy;
end;

function TShareMemStream.GetLock(ATimeOut: DWORD): Boolean;
var
  wr: TWaitResult;
begin
  wr := FEvent.WaitFor(ATimeOut);
  Result := wr = wrSignaled;
end;

procedure TShareMemStream.ReleaseLock;
begin
  FEvent.SetEvent;
end;

function TShareMemStream.Write(const Buffer; Count: Integer): Longint;
begin
  Result := 0;
  if (Size - Position) >= Count then
  begin
    System.Move(Buffer, Pointer(Longint(Memory) + Position)^, Count);
    Position := Position + Count;
    Result := Count;
  end;
end;

end.


测试Demo下载

标签:begin,end,Delphi,TShareMemStream,ACCESS,ms,封装,sa,共享内存
From: https://www.cnblogs.com/YXGust/p/16726151.html

相关文章

  • ASEMI快恢复二极管6A10参数,6A10规格,6A10封装
    编辑-ZASEMI快恢复二极管6A10参数:型号:6A10最大重复峰值反向电压(VRRM):1000V最大RMS电桥输入电压(VRMS):700V最大直流阻断电压(VDC):1000V最大平均正向整流输出电流(IF):6A峰值......
  • 海康摄像机使用GB28181接入SRS服务器的搭建步骤---封装docker镜像运行容器的方式,本篇
    使用第三方提供的镜像说明:这个是我在网上找的,没有实际验证及使用过,具体效果未知,看下文,我采用的是自己依据官方基础镜像进一步二次封装的镜像地址:https://hub.docker.com/......
  • Delphi 11.2的一个问题
    https://quality.embarcadero.com/browse/RSP-39499functionTAndroidVirtualKeyboard.DefineNativeView(constAObject:TFmxObject):JView;functionIsNativeCon......
  • SF68-ASEMI插件封装二极管SF68
    编辑-ZSF68在R-6封装里采用的1个芯片,其尺寸都是84MIL,是一款插件封装二极管。SF68的浪涌电流Ifsm为200A,漏电流(Ir)为10uA,其工作时耐温度范围为-55~150摄氏度。SF68采用GPP......
  • 使用nssm将exe程序或bat封装成windows服务
    nssm是一个轻量级服务封装程序,它可以将普通exe或bat程序封装成windows服务,使之像windows服务一样运行。同类型的工具还有微软自己的srvany,不过nssm更加简单易用,并且功能强......
  • delphi TMS FlexCel 导出HTML
    TMSFlexCel导出HTML属性和方法TFlexCelHtmlExport用于将Excel文件导出为HTML的组件。unitFlexCel.RenderTFlexCelHtmlExport.CreateconstructorCreate(const......
  • MBR30300VPT-ASEMI肖特基MBR30300VPT二极管TO-247封装
    编辑:llMBR30300VPT-ASEMI肖特基MBR30300VPT二极管TO-247封装型号:MBR30300VPT品牌:ASEMI封装:TO-247正向电流:30A反向电压:300V引线数量:3芯片个数:2芯片尺寸:102MIL漏电......
  • delphi TcxGrid取消筛选
       19.2 以前的用007大佬的这句 cxgrdbtblvwGrid1DBTableView2.DataController.Filter.Clear;  以后的用DataController.findcriteria.text:=''; ......
  • 算法 玩转数据结构 2-2 二次封装属于我们自己的数组
    1重点关注1.1索引使用数组最大的优点:快速查询。scores[2]·数组最好应用于“索引有语意”的情况。·但并非所有有语意的索引都适用于数组(例如,以身份......
  • el-select封装(单选框、多选框、全选功能)
    先看看设计图:网上找了一溜,都是扯淡,样式也没个自己动手吧,先把样式搞定popper-class="xx-option"所有单选框都用:after和:before类+定位实现样式逻辑复杂点,再加上......