delphi destructor tthread

delphi - Una forma adecuada de destruir un objeto TThread



destructor (2)

Mucho de lo que sugieres ya se realiza en el destructor TThread.Destroy, e invocar a TMyThread.free hará exactamente lo que sugieras. Para limpiar cualquier objeto propiedad de la clase de subproceso, puede realizarlo en el evento OnTerminate, que se invocará como parte de la lógica de cierre de subproceso.

Esta pregunta puede parecer trivial, pero espero que no la ignore.
Antes de destruir un objeto TThread, generalmente es necesario esperar hasta que finalice el hilo que llamó al método TThread.Execute (), solo entonces podemos estar seguros de que, por ejemplo, los objetos destruidos dentro del destructor de la clase ya no se tienen acceso. Por lo tanto, es necesario llamar a Terminate para establecer el indicador Terminado que el hilo debe verificar para saber si salir o no, y luego llamar al método WaitFor ().

Como el hilo puede estar suspendido, creo que es bueno reanudarlo antes de llamar a WaitFor, ya que, de lo contrario, el hilo de llamada estaría bloqueado. Y debido a que el hilo se puede suspender varias veces, se debe reanudar el mismo número de veces, ¿verdad?

while Suspended do Resume;

Si el hilo fue creado suspendido, no tenemos que preocuparnos de que se invoque el método TThread.Execute () cuando reanudamos el hilo solo para terminarlo; no lo hará (corrígeme si me equivoco).

Lo que he indicado sugiere usar las siguientes líneas de código para cada objeto TThread liberado:

MyThread.Terminate; while MyThread.Suspended do MyThread.Resume; MyThread.WaitFor; MyThread.Free;

Desafortunadamente, cuando destruimos nuestra aplicación que ha creado múltiples hilos, escribir un código de este tipo para cada objeto TThread que se destruye innecesariamente hace que el código sea muy largo y quizás incluso opaco.

Por lo tanto, llegué a la conclusión de que todos estos podrían colocarse dentro de un destructor invalidado de la clase TThread, gracias al cual sería suficiente llamar a MyThread.Free (o MyThread.Terminate si MyThread.FreeOnTerminate está establecido) sin importar si el destruido objeto es un objeto TThread o no:

destructor TMyThread.Destroy; begin //if FreeOnTerminate, the calling thread cannot wait for itself if GetCurrentThreadId <> ThreadId then begin Terminate; while Suspended do Resume; WaitFor; end; {free all objects created in this class} inherited Destroy; end;

Perdóname por hacer una pregunta tan básica. Me gustaría, sin embargo, conocer sus opiniones sobre esta forma, espero que sea universal, de destruir objetos TThread. Hice estas preguntas porque aprendí de los códigos de mis compañeros de trabajo que generalmente usaban el primer ejemplo de código para destruir dichos objetos, pero nunca solían comprobar si los hilos que se esperaban no estaban suspendidos, lo que consideré un poco peligroso si los hilos podría estar suspendido en algún lugar del código. Por lo tanto, traté de encontrar una forma universal de destruir los objetos de esta clase que haría el código más claro y seguro. Espero no haberlo empeorado, ¿qué opinas?

Gracias por sus sugerencias de antemano.


No existe una forma universal de detener un hilo, al igual que no existe una forma universal de detener (con gracia) un proceso. Cada uno es diferente

Para algunos subprocesos, es suficiente establecer su propiedad Terminated mediante el método Terminate . Sin embargo, otros subprocesos llaman a funciones como GetMessage o MsgWaitForMultipleObjects , que se bloquearán hasta que ocurra algo, como que llegue un mensaje o que se envíe una señal al asa del núcleo. TThread.Terminate no puede hacer que ninguna de estas cosas suceda, por lo que no puede hacer que esos subprocesos dejen de ejecutarse. Cuando escribí hilos como esos, proporcioné mis propias funciones para notificarles que dejen de correr. Podría llamar a PostThreadMessage para forzar un mensaje en la cola de la secuencia, o podría señalar el evento que la clase de subproceso ha proporcionado para notificarlo de una solicitud de terminación.

No te preocupes por reanudar un hilo suspendido. Realmente no deberías suspenderlos de todos modos. La única forma segura de suspender un hilo es que el hilo se suspenda, y una vez que lo tienes, tienes garantizado que tienes al menos dos hilos que controlan cuándo se ejecuta el hilo: el propio hilo para suspenderlo, y al menos otro hilo hilo para reanudarlo de nuevo. Un hilo debe tener el control de su propia ejecución.

Sería genial si TThread.Terminate fuera virtual. Entonces, cada clase de subproceso podría proporcionar una forma personalizada de notificarse a sí misma que debería dejar de ejecutarse. Algunos podrían simplemente configurar Terminated , y otros podrían publicar mensajes, señalar eventos o hacer lo que necesiten. Sin embargo, tal como es, el método no virtual no funciona bien con hilos que pasan mucho tiempo esperando otras cosas. La forma actual solo funciona para hilos que pueden sondear con frecuencia sus propiedades Terminated .

Algunos hilos tienen sus propiedades FreeOnTerminate establecidas. Para esos hilos, su código no es seguro. Técnicamente, no es seguro llamar a ningún método sobre dichos objetos, ya que el hilo podría terminar en cualquier momento. Pero incluso si sabe que el hilo todavía se está ejecutando y el objeto de hilo todavía existe, el objeto definitivamente dejará de existir en algún momento después de la llamada a Terminate . No puede llamar a WaitFor en un objeto de subproceso libre de terminación y definitivamente no puede llamar a Free .