2012-02-23 12 views
7

私は子プロセスを実行し、終了するために子プロセスを待たずに(おそらくミューテックスで)それを同期したいと思います:親子プロセスの実行を同期する方法は?

親:

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の)は、ループを出ないことです。
何が間違っていますか?

答えて

11

あなたはミューテックスのレースを持っています。私は非常にあなたの究極の目標が何であるかを動作することはできませんが、私はイベントという疑いを持っている

child: create mutex 
parent: open mutex 
child: destroy mutex 

しかし、何が起こることができることは

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

です:あなたは、次の手順を望んでいます実際にあなたが探しているものです。親で

  1. という名前のイベントを作成します。
  2. 非シグナルにイベントを設定します。
  3. 子プロセスを作成します。
  4. イベントが通知されるまで待ちます。子供で

  1. は、いくつかの処理を行います。
  2. 名前付きイベントを開きます。
  3. それによってその待機から親を解放し、合図するイベントを設定します。非常に高いレベルで

必要なコードは次のようになります。私はすべてのエラーが含まれていませんでした

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

子供

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

チェック。私はあなたがいくつかを追加できると確信しています。また、イベントラッパークラスSyncObjsがより便利であることがあります。


最後に、コードにビジーループがあります。それはどんな問題の解決策でもありません。あなたがビジーなループを書くことが今までにあったのであれば、デザインが間違っているという信号としてそれを取るべきです。重要なのは、コード内で、それを動作させることができれば、親プロセスは子プロセスを待っている間に100%CPU使用率を燃やすということです。

+0

10x、私のデザインが間違っていると思われました。この場合、WaitForSingleObjectを使用する方法を理解できませんでした。説明したようなイベントを処理する正しいコードを書く方法を教えてください。 – ZigiZ

+0

OK、疑似コードを追加しました。それは超簡単。あなたは、MSDNのドキュメントを読む方法をはっきりと知っています。私はあなたがここからそれを解読できると確信しています。 –

+0

ブリリアント! 10倍! – ZigiZ

関連する問題