요구에 따라 델파이 스레드 모니터링을 시작/중지하는 방법은 무엇입니까?
-
20-09-2019 - |
문제
델파이의 특정 레지스트리 변경 사항을 모니터링 할 수있는 방법을 찾고 있습니다. 찾았습니다 해결책 at About.com :
procedure TRegMonitorThread.Execute;
begin
InitThread; // method omitted here
while not Terminated do
begin
if WaitForSingleObject(FEvent, INFINITE) = WAIT_OBJECT_0 then
begin
fChangeData.RootKey := RootKey;
fChangeData.Key := Key;
SendMessage(Wnd, WM_REGCHANGE, RootKey, LongInt(PChar(Key)));
ResetEvent(FEvent);
RegNotifyChangeKeyValue(FReg.CurrentKey, 1, Filter, FEvent, 1);
end;
end;
end;
내 응용 프로그램에서는이 스레드가 주문형을 시작하고 중지해야하지만 위의 코드는이를 허용하지 않습니다. 종료 된 플래그를 설정하는 것만으로는 그렇지 않습니다.
어떻게 든 스레드에 대기를 중지 한 다음 해방하고 필요할 때 새로운 것을 만들도록 말하는 것이 충분할 것입니다. 이 코드를 어떻게 변경하여이를 달성하려면 어떻게해야합니까?
해결책
사용 WaitForMultipleObjects()
대신 두 이벤트 배열이 있습니다 WaitForSingleObject()
. 스레드 클래스에 수동 재설정 이벤트를 추가하고 설정 한 후에 신호를 보내십시오. Terminated
에게 True
. 두 이벤트 중 신호를받은 반환 값을 확인하고 그에 따라 행동하십시오.
편집하다:
아이디어를 보여주기위한 최소 Delphi 2009 코드. 추가해야합니다 SyncObjs
중고 장치 목록에 추가하십시오
fTerminateEvent: TEvent;
~로 private
스레드 클래스의 섹션.
constructor TTestThread.Create;
begin
inherited Create(TRUE);
fTerminateEvent := TEvent.Create(nil, True, False, '');
// ...
Resume;
end;
destructor TTestThread.Destroy;
begin
fTerminateEvent.SetEvent;
Terminate; // not necessary if you don't check Terminated in your code
WaitFor;
fTerminateEvent.Free;
inherited;
end;
procedure TTestThread.Execute;
var
Handles: array[0..1] of THandle;
begin
Handles[0] := ...; // your event handle goes here
Handles[1] := fTerminateEvent.Handle;
while not Terminated do begin
if WaitForMultipleObjects(2, @Handles[0], False, INFINITE) <> WAIT_OBJECT_0 then
break;
// ...
end;
end;
질문에 코드를 추가하면됩니다. 스레드 인스턴스를 해제하려고 시도하면 스레드를 차단 해제하는 데 필요한 모든 것이 수행됩니다 (필요한 경우).
다른 팁
대신 Infinite에서는 기간이 지나면 WaitforsingleObject Time Out이 있어야합니다. 그렇게하면 루프가 계속되고 종료됩니다.
procedure TRegMonitorThread.Execute;
begin
InitThread; // method omitted here
while not Terminated do
begin
if WaitForSingleObject(FEvent, 1000) = WAIT_OBJECT_0 then
begin
fChangeData.RootKey := RootKey;
fChangeData.Key := Key;
SendMessage(Wnd, WM_REGCHANGE, RootKey, LongInt(PChar(Key)));
ResetEvent(FEvent);
RegNotifyChangeKeyValue(FReg.CurrentKey, 1, Filter, FEvent, 1);
end;
end;
end;
방법 tthread.suspend 및 tthread.resume 방법은 이론적으로 일시적인 스톱 스레드를 사용하는 데 사용될 수 있지만 Delphi 2010은 이제 사용하기에 안전하지 않다는 것을 인정합니다. 보다 tthread.resume은 Delphi-2010에서 더 이상 사용되지 않습니다. 그리고 http://msdn.microsoft.com/en-us/library/ms686345%28vs.85%29.aspx
이것은 작동합니다. 아래에서와 같이 작은 변경 만하며 이제 Ternatine에 전화 할 때 다음과 같습니다.
TRegMonitorThread = class(TThread)
...
public
procedure Terminate; reintroduce;
...
procedure TRegMonitorThread. Terminate; // add new public procedure
begin
inherited Terminate;
Windows.SetEvent(FEvent);
end;
procedure TRegMonitorThread.Execute;
begin
InitThread;
while not Terminated do
begin
if WaitForSingleObject(FEvent, INFINITE) = WAIT_OBJECT_0 then
begin
if Terminated then // <- add this 2 lines
Exit;
...
end;
end;
end;