delphi – 如何同步父/子进程执行?

我想执行子进程并同步它(可能与Mutex),而不等待子进程终止:

家长:

program Project1;
{$APPTYPE CONSOLE}
uses
  Windows,ShellApi,SysUtils,Dialogs;

procedure ShellExecEx(Wnd: HWND; const AExeFilename,AParams: string);
const
  SEE_MASK_NOZONECHECKS = $00800000;
  SEE_MASK_WAITFORINPUTIDLE = $02000000;
  SEE_MASK_NOASYNC = $00000100;
var
  Info: TShellExecuteInfo;
begin
  FillChar(Info,SizeOf(Info),0);
  Info.Wnd := Wnd;
  Info.cbSize := SizeOf(Info);
  Info.fMask := SEE_MASK_FLAG_NO_UI or SEE_MASK_NOZONECHECKS or
    SEE_MASK_NOASYNC
    //or SEE_MASK_WAITFORINPUTIDLE (works only with UI app ???)
    //or SEE_MASK_NO_CONSOLE
    //or SEE_MASK_NOCLOSEPROCESS
    ;
  Info.lpVerb := '';
  Info.lpFile := PChar(AExeFilename);
  Info.lpParameters := PChar(AParams);
  Info.lpDirectory := PChar(ExtractFilePath(AExeFilename));
  Info.nShow := SW_SHOWnorMAL;
  if not ShellExecuteEx(@Info) then
    RaiseLastOSError;
  CloseHandle(Info.hProcess);
end;

var
  Mutex: THandle = 0;
  Error: DWORD;
begin
  OutputDebugString('Project1 : 1');

  ShellExecEx(0,'Project2.exe','');

  // synchronize
  repeat
    // attempt to create a named mutex
    Mutex := CreateMutex(nil,False,'F141518A-E6E4-4BC0-86EB-828B1BC48DD1');
    Error := GetLastError;
    if Mutex = 0 then RaiseLastOSError;
    CloseHandle(Mutex);
  until Error = ERROR_ALREADY_EXISTS;

  OutputDebugString('Project1 : 3');
end.

儿童:

program Project2;
{$APPTYPE CONSOLE}
uses
  SysUtils,Windows,Dialogs;

var
  Mutex: THandle = 0;
begin
  OutputDebugString('Project2 : 2');
  // attempt to create a named mutex and acquire ownership
  Mutex := CreateMutex(nil,True,'F141518A-E6E4-4BC0-86EB-828B1BC48DD1');
  if Mutex = 0 then RaiseLastOSError;

  // do something

  ReleaseMutex(Mutex);
  CloseHandle(Mutex); // <- at this point Program1.exe should exit the repeat loop

  ShowMessage('ok from Project2');
end.

我期待看到输出

Project1 : 1
Project2 : 2
Project1 : 3

问题是有时父(Project1.exe)没有退出循环.
我究竟做错了什么?

解决方法

你在互斥锁上有一场比赛.您希望以下顺序:
child:  create mutex
parent: open mutex
child:  destroy mutex

但可能发生的是

child:  create mutex
child:  destroy mutex
parent: open mutex (fails because mutex is destroyed)

我无法确定你的最终目标是什么,但我怀疑事件实际上是你在寻找什么.

在父母:

>创建命名事件.
>将事件设置为无信号.
>创建子进程.
>等到事件发出信号.

在孩子:

>做一些处理.
>打开命名事件.
>将事件设置为发信号,从而从父级等待中释放父级.

在非常高的级别,您需要的代码将如下所示:

Event = CreateEvent(nil,EventName);
//create it manual reset,set to non-signaled
ShellExecEx(....);
WaitForSingleObject(Event);

儿童

Event = CreateEvent(nil,EventName);
//do stuff
SetEvent(Event);

我没有包含任何错误检查.我相信你可以添加一些.您可能还会发现SyncObjs中的事件包装器类更方便.

最后,您的代码一个繁忙的循环.这几乎不是任何问题的解决方案.如果您发现自己编写了一个繁忙的循环,那么您应该将其视为设计不正确的信号.关键是,在您的代码中,如果可以使其工作,父进程将在等待子进程时消耗100%的cpu利用率.

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...