Pregunta

He estado buscando una manera de controlar los cambios de registro específicas en Delphi. Encontrado un solución en 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;

En mi solicitud que tendrá que iniciar y detener este hilo en la demanda, pero el código anterior no permite eso. Sólo el establecimiento del indicador Terminado no lo hará.

Sería suficiente para decirle de alguna manera el hilo que dejar de esperar, a continuación, liberarla y crear uno nuevo cuando sea necesario. ¿Cómo puedo cambiar el código para lograr eso?

¿Fue útil?

Solución

Uso WaitForMultipleObjects() con una serie de dos eventos en lugar de WaitForSingleObject(). Añadir un evento de rearme manual a la clase de hilo, y señalar que después de haber establecido Terminated a True. Comprobar el valor de retorno cuál de los dos eventos se ha señalado, y actuar en consecuencia.

Editar

Algunos mínima de código de Delphi 2009 para demostrar la idea. Usted tiene que agregar SyncObjs a la lista de unidades usadas, y añadir

  fTerminateEvent: TEvent;

a la sección private de su clase de hilo.

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;

Sólo tiene que añadir el código en tu pregunta a la misma. Simplemente tratando de liberar la instancia hilo va a hacer todo lo necesario para desbloquear el hilo (si es necesario).

Otros consejos

En lugar de INFINITO usted debe tener tiempo WaitForSingleObject a cabo después de un período. De esta forma el bucle continúa y se comprueba Terminado.

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;

El TThread.Suspend métodos y TThread.Resume teóricamente podría ser utilizado para las discusiones parada temporal, sino como Delphi 2010 reconoce ahora que no son seguros para su uso. Ver TThread.resume está en desuso en Delphi-2010 lo que se debe utilizar en su lugar? y http://msdn.microsoft.com/en-us/library/ms686345%28VS.85%29.aspx

Esto funciona, sólo hacer pequeños cambios que a continuación y ahora cuando se llama Terminar:

  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;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top