2010-03-18 3 views
6

나는 언제든지 액세스 할 수 있도록 내 응용 프로그램 (또는 COM API) 인스턴스 1 개와 인스턴스 1 개만을 원한다는 공통 리소스를 가지고 있습니다. 뮤텍스를 사용하여이 리소스를 보호하려고했지만 호스트 닷넷 응용 프로그램의 여러 스레드가 COM 개체에 액세스하려고하면 뮤텍스가 해제 된 것처럼 보이지 않습니다. 이것은 내가 자원을 보호하는 데 사용한 코드입니다. 나는 동시에 스레드를 실행하는 경우뮤텍스를 사용하여 공통 리소스를 어떻게 보호합니까?

repeat 
    Mutex := CreateMutex(nil, True, PChar('Connections')); 
until (Mutex <> 0) and (GetLastError <> ERROR_ALREADY_EXISTS); 
    try 
    //use resource here! 
    finally 
    CloseHandle(Mutex); 
    end; 

는 첫 번째 스레드 (뮤텍스를 만들 수있는 첫 번째되고, 명백하게)을 통해의를 얻을 수 있지만, 이후 스레드는 반복 루프에 걸려있다. 5 초 간격으로 각 스레드를 실행하면 모두 괜찮습니다.

나는 여기서 mutexes를 올바르게 사용하지 않는다고 생각하지만이 작업을 수행하는 방법에 대한 문서는 거의 찾지 못했습니다.

아이디어가 있으십니까?

답변

14

뮤텍스를 잘못 사용하고 있습니다. 당신은 끊임없이 그것을 재창조하지 말고 그것을 기다리고 있어야합니다. 초기화하는 동안

: 당신이 뮤텍스는 글로벌 때문에, 당신은 작은 선물을 선택해야

CloseHandle(Mutex); 

또한 마무리 동안 자원을

if WaitForSingleObject(Mutex, INFINITE) <> WAIT_OBJECT_0 then 
    RaiseLastOSError; 
try 
    // Use resource here 
finally 
    ReleaseMutex(Mutex) 
end; 

에 액세스 할

Mutex := CreateMutex(nil, False, 'Connections'); 
if Mutex = 0 then 
    RaiseLastOSError; 

이름에 대한 "연결"보다 더 고유합니다. 우리는 우리 끝에 GUID를 추가했습니다.

+0

CreateMutex의 두 번째 매개 변수를 True로 설정 한 경우에만 작동한다는 것을 추가해야합니다. 그렇지 않으면 이전에 행 쓰레드와 동일한 문제가 발생합니다. – Steve

+0

Odd. WaitForSingleObject 호출은 사용자를 위해 뮤텍스를 가져와야합니다. MSDN 예제는 False도 사용합니다. http://msdn.microsoft.com/en-us/library/ms686927%28VS.85%29.aspx –

+1

Craig가 옳습니다. 내 추천은 * 절대로 * 두 번째 매개 변수에 대해 'True'를 전달하지 않는 것입니다. 그 이유는 함수가 반환 될 때 실제로 뮤텍스를 소유하고 있는지 알 수 없기 때문입니다. 게다가, 생성시에는 어쨌든 뮤텍스를 소유 할 필요가 없을 것입니다. 프로그램이 시작될 때 mutex * once *를 만듭니다. 그런 다음 프로그램을 실행하면서 획득하고 해제하십시오. 프로그램이 종료되면 핸들을 닫으십시오. 뮤텍스를 소유 할 필요가있을 때마다 뮤텍스를 만들고 파괴하지 마십시오. –

10

간단한 데모 코드로 시도해보십시오. 응용 프로그램의 여러 인스턴스를 시작하고 당신은 그들이 뮤텍스를 공유하는 방식 배경색에서 볼 수있다 : 나는 일을 단순화 SyncObjs 단위에서 TMutex 클래스를 사용하기로 결정했습니다

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    fMutex := SyncObjs.TMutex.Create(nil, False, 'GlobalUniqueName'); 
end; 

procedure TForm1.FormDestroy(Sender: TObject); 
begin 
    fMutex.Free; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    Color := clRed; 
    Update; 
    fMutex.Acquire; 
    try 
    Color := clGreen; 
    Update; 
    Sleep(5 * 1000); 
    finally 
    fMutex.Release; 
    end; 
    Color := clBtnFace; 
end; 

참고.

+1

이것은 좋은 대답이기는하지만 크레이그가 먼저 올렸고 상대가 당신보다 적습니다. 둘 다 좋은 대답이기 때문에 두 가지 모두 받아 들일 수 있었으면 좋겠습니다. – Steve

관련 문제