delphi - termina todos los hilos (TThread) en la aplicación de cierre
Pregunta
Mi aplicación es un servidor TCP / IP, con el hilo principal creado solo una vez & amp; escuchando todo el tiempo Cuando el nuevo cliente se conecta, el hilo principal crea el nuevo hilo del tipo TClientThread
. Sin embargo, no hay una lista de subprocesos en ejecución del Cliente, ya que eso complicaría un poco mi aplicación ... ¿hay alguna forma de ejecutar " terminar? & Quot; Método en todos los subprocesos, incluso si el subproceso está ocupado (en mi caso "ocupado" significa que está esperando los datos, donde el tiempo de espera establecido es de unos 30 segundos ... así que tengo que eliminarlo de todos modos, sin esperar). ?
La simple aplicación de cierre parece no ejecutar " terminar " Método en los subprocesos, que termina con pérdidas de memoria reportadas por FastMM ...
Solución
Las pérdidas de memoria en el apagado no son nada de qué preocuparse: preocuparse por liberar la memoria antes de devolver el control al sistema operativo es una pérdida de tiempo y ralentiza innecesariamente la salida de la aplicación. Todo lo que realmente necesita hacer es asegurarse de que todos los datos se hayan guardado y todos los manejadores interproceso (como semáforos y mutexes) liberados correctamente, y salir.
Para notificar a los clientes, lo mejor que puedes hacer sería una estrategia como esta:
- Agregue todos los subprocesos de manejo del cliente a alguna lista en algún lugar (con un bloqueo adecuado en la creación, destrucción e iteración)
- Haga que los subprocesos de los clientes se eliminen de la lista al finalizar, y elimine el último elemento de la lista para establecer un evento (evento de restablecimiento manual, por ejemplo,
TEvent
en SyncObjs) si el servidor se está cerrando - Introduzca el sondeo (por ejemplo,
select
o equivalente con un tiempo de espera) u otro tipo de interrupción (por ejemplo, SO_RCVTIMEO / SO_SNDTIMEO) en lo que de otra manera serían rutinas de bloqueo de larga ejecución, monitoreando la propiedad terminada - Al apagar, bloquee la lista e itere a través de ella, llamando a
Terminate
, y luego espere a que se señale el evento; por supuesto, la toma de escucha que agrega elementos a la lista debe cerrarse y se sabe que está cerrada antes de iterar a través de la lista
Otros consejos
Parece que este artículo puede ayudar
Lo que verás si haces clic en ese enlace:
Usando semáforos en Delphi, Parte 2: El conjunto de conexiones
Por: Cary Jensen
Resumen: los semáforos se utilizan para coordinar múltiples hilos y procesos Que los semáforos proporcionan. múltiples hilos con simultaneo El acceso a un recurso compartido es resaltado por el Clase TFixedConnectionPool descrita en este artículo.
Utilizo un KillThreadList: TList global. Lo superviso en mi hilo como:
while (Not Terminated) do
begin
inc(Inker);
if (WaitForSingleObject(FTick, finterval) = WAIT_TIMEOUT) then
Begin
if Inker >= 10 then
Begin
ProcessTables;
Inker := 0;
sleep(1000);
End;
if KillThreadList.Contains(ThreadID) = True then Terminate;
End;
end;
También hago pruebas para KillThreadList en mis procesos para que pueda dejar de participar antes de que se complete, donde sea seguro hacerlo.
Transfiero el evento OnTerminate al hilo principal y elimino el ThreadID de la lista de muerte allí. Utilizo este modelo ampliamente y todavía no me ha fallado.
procedure TfrmProcessQualcommLocations.OnTerminateThread;
var
ThreadID : Cardinal;
i : integer;
aStatusBar :TStatFrame;
begin
ThreadID := (Sender as Tthread).ThreadID;
for i := 0 to StatusBarList.Count -1 do
Begin
if StatusBarList.Items[i].ThreadID = ThreadID then
Begin
aStatusBar := StatusBarList.Items[i];
KillThreadList.Extract(ThreadID);
StatusBarList.Extract(aStatusBar);
aStatusBar.Free;
break;
End;
End;
self.Refresh;
end;
En el caso anterior, también estoy eliminando algunas cosas de GUI.
Espero que ayude. SpringerRider