2012-02-23 43 views
7

Tôi muốn thực hiện một quá trình con và đồng bộ hóa nó (có thể với Mutex) mà không cần chờ cho quá trình con để chấm dứt:Làm cách nào để đồng bộ hóa quá trình thực hiện quy trình Phụ huynh/Con?

phụ huynh:

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. 

Child:

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. 

Tôi hy vọng sẽ thấy kết quả của:

Project1 : 1 
Project2 : 2 
Project1 : 3 

Vấn đề là đôi khi Parent (Project1.exe) không thoát khỏi vòng lặp.
Tôi đang làm gì sai?

Trả lời

11

Bạn có cuộc đua trên mutex. Bạn đang hy vọng cho các trình tự sau:

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

Nhưng những gì có thể xảy ra là

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

Tôi không thể làm việc khá ra những mục tiêu cuối cùng của bạn là nhưng tôi có một sự nghi ngờ rằng một sự kiện thực sự là những gì bạn đang tìm kiếm.

Trong phụ huynh:

  1. Tạo một sự kiện được đặt tên.
  2. Đặt sự kiện thành không có tín hiệu.
  3. Tạo quy trình con.
  4. Đợi cho đến khi sự kiện được báo hiệu.

Trong con:

  1. Do một số chế biến.
  2. Mở sự kiện được đặt tên.
  3. Đặt sự kiện thành tín hiệu, do đó phát hành phụ huynh từ lúc chờ đợi.

Trong mức rất cao mã bạn cần sẽ trông như thế này:

Chánh

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

Child

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

Tôi đã không bao gồm bất kỳ lỗi kiểm tra. Tôi chắc rằng bạn có thể thêm một số. Bạn cũng có thể thấy rằng lớp trình bao bọc sự kiện trong SyncObjs thuận tiện hơn.


Cuối cùng, mã của bạn có vòng lặp bận. Đó là gần như không bao giờ là giải pháp cho bất kỳ vấn đề.Nếu bao giờ bạn thấy mình viết một vòng lặp bận rộn, bạn nên dùng nó như một tín hiệu rằng thiết kế không chính xác. Vấn đề là, trong mã của bạn, nếu nó có thể được thực hiện để làm việc, quá trình cha mẹ sẽ đốt cháy 100% sử dụng CPU trong khi chờ đợi về quá trình con.

+0

10x, tôi nghi ngờ rằng thiết kế của tôi không chính xác. Tôi không thể nhận ra cách sử dụng 'WaitForSingleObject' trong trường hợp này ... Bạn có thể chỉ cho tôi cách viết mã đúng để xử lý các sự kiện như bạn đã giải thích không? – ZigiZ

+0

OK, tôi đã thêm một số mã giả. Nó rất dễ. Bạn biết rõ làm thế nào để đọc tài liệu MSDN và tôi chắc chắn bạn có thể tự mình crack từ đây. –

+0

Rực rỡ! 10x! – ZigiZ

Các vấn đề liên quan