Pregunta

Esta pregunta involucra a Delphi y Xe específicamente despreciando suspender y reanudar. He leído otras publicaciones y no he encontrado un uso similar hasta ahora, así que voy a seguir adelante y pedir una discusión.

Lo que me gustaría saber es una mejor manera de detener un hilo cuando no es necesario.

Tenemos una clase de Delphi que hemos usado durante años que es básicamente una cola FIFO que está asociada con un proceso roscado. La cola acepta un objeto de datos en el hilo principal y si el hilo está suspendido, lo reanudará.

Como parte del proceso de ejecución del hilo, el objeto sale de la cola y se procesa en el hilo. Por lo general, esto es para hacer una búsqueda de base de datos.

Al final del proceso, una propiedad del objeto se actualiza y se marca como está disponible para el hilo principal o se pasa a otra cola. El último (bueno, realmente es el primer) paso del proceso de ejecución es verificar si hay más elementos en la cola. Si lo existe, continúa, de lo contrario se suspende a sí mismo.

La clave es que la única acción de suspensión está dentro del bucle de ejecución cuando se completa, y el único currículum durante las operaciones normales se llama cuando se coloca un nuevo elemento en la cola. La excepción es cuando se termina la clase de cola.

La función de currículum se parece a esto.

process TthrdQueue.MyResume();
  begin
    if Suspended then begin
      Sleep(1); //Allow thread to suspend if it is in the process of suspending
      Resume();
    end;
  end;

La ejecución se parece a esto

process TthrdQueue.Execute();
  var
    Obj : TMyObject;
  begin
    inherited;
    FreeOnTerminate := true;
    while not terminated do begin
      if not Queue.Empty then begin
        Obj :=  Pop();
        MyProcess(Obj);  //Do work
        Obj.Ready := true;
      end
      else
        Suspend();  // No more Work
    end;   //Queue clean up in Destructor
  end;  

La rutina de empuje Tthrdqueue llama a MyResume después de agregar otro objeto en la pila. Myresume solo llama al currículum si el hilo está suspendido.

Al apagar, configuramos terminando a True y llame a MyResume si está suspendido.

¿Fue útil?

Solución

Recomendaría la siguiente implementación de Tthrdqueue:

type
  TthrdQueue = class(TThread)
  private
    FEvent: THandle;
  protected
    procedure Execute; override;
  public
    procedure MyResume;
  end;

implementation

procedure TthrdQueue.MyResume;
begin
  SetEvent(FEvent);
end;

procedure TthrdQueue.Execute;
begin
  FEvent:= CreateEvent(nil,
                       False,    // auto reset
                       False,    // initial state = not signaled
                       nil);
  FreeOnTerminate := true;
  try
    while not Terminated do begin
      if not Queue.Empty then begin
        Obj :=  Pop();
        MyProcess(Obj);  //Do work
        Obj.Ready := true;
      end
      else
        WaitForSingleObject(FEvent, INFINITE);  // No more Work
    end;
  finally
    CloseHandle(FEvent);
  end;
end;

Otros consejos

En lugar de suspender el hilo, hazlo dormir. Haga que bloquee un mango esperable, y cuando el mango se indique, el hilo se despertará.

Tiene muchas opciones para objetos esperables, incluidos eventos, objetos mutex, semáforos, colas de mensajes, tuberías.

Supongamos que elige usar un evento. Haz que sea un evento de reinicio automático. Cuando la cola esté vacía, llame al evento WaitFor método. Cuando algo más puega la cola o quiera dejar de fumar, haga que llame al evento SetEvent método.

Preferí la técnica es usar la cola de mensajes del sistema operativo. Reemplazaría su objeto de cola con mensajes. Entonces, escriba un estándar GetMessage círculo. Cuando la cola está vacía, se bloqueará automáticamente para esperar un nuevo mensaje. Convierta una solicitud de terminación en solo otro mensaje. (Los TThread.Terminate El método simplemente no es una función muy útil una vez que comienzas a hacer algo interesante con los hilos porque no es virtual).

Hay una biblioteca para permitir la implementación de la cola de consumidor de productores en Delphi usando variables de condición. Este escenario es en realidad el ejemplo discutido.

El ejemplo clásico de las variables de condición es el problema del productor/consumidor. Uno o más hilos llamados productores producen elementos y los agregan a una cola. Los consumidores (otros hilos) consumen artículos eliminando los artículos producidos de la cola.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top