2010-11-16 6 views

Respuesta

8

Calling Application.ProcessMessages se considera generalmente un olor código. Deje que su hilo principal permanezca inactivo si no tiene nada que hacer.

Si dirige una empresa y necesita que uno de sus trabajadores corra a la tienda y compre algunos de los suministros que tanto necesita, ¿podría caminar por la puerta hasta que regrese, o preferiría sentarse en su oficina y descanse y espérelo, y descubra que los suministros están aquí porque lo oye entrar por la puerta? De cualquier manera, tomará la misma cantidad de tiempo, pero la primera forma te desgastará las piernas.

De manera similar, en lugar de tener su UI mirando el hilo, haga que el hilo informe a la IU. Una forma de hacerlo es hacer que el subproceso use PostMessage para enviar un mensaje personalizado al formulario que lo lanzó una vez que finaliza, y poner un controlador de mensajes en el formulario para responderlo.

+0

Mason: Es posible que desee decir Application.ProcessMessages y no Application.PostMessages. – jachguate

+0

Hay algunos casos en los que todo lo que tienes que hacer es esperar ...por ejemplo, para dejar que la aplicación termine. Si usa WaitFor en un hilo (ya conocido) de lazy-to-terminate ... un usuario (y Windows) puede pensar que no responde ... – jachguate

+0

Mason, muchas gracias por su respuesta, ¿puede dar un ejemplo simple (código fuente) de tu respuesta? – Salvador

2

Parece correcto (si es correcto significa que hace el trabajo). Lo que cambiaría es esperar un poco más de tiempo (50 ms se ve bien para mantener la aplicación en buen estado) sin consumir CPU.

while WaitForSingleObject(MyThread.Handle, 50) = WAIT_TIMEOUT do 
    Application.ProcessMessages; 
ShowMessage('i am done'); 

Seguro que hay otras maneras de hacerlo ... > < broma pero por lo general se deba a uno de los principales principios de la ingeniería:

si funciona, no lo toques! </joke >

+0

No es una buena idea llamar a Application.ProcessMessages() cuando no hay mensajes que procesar. Debería usar MsgWaitForMultipleObjects() en su lugar para detectar cuándo la cola de mensajes tiene algo que procesar. –

+0

@ Remy: gracias por esa información ... Normalmente evitaré llamar al método ProcessMessages, pero a veces lo hice, principalmente porque no tenía idea de un mejor enfoque. Comprobaré en MsgWaitForMultipleObjects para aprender y mejorar eso. ¡Gracias de nuevo!. :) – jachguate

1

Aunque se ve bien, como jachguate usaría un valor de tiempo de espera mayor que 0 también. Si usa WaitForSingleObject(MyThread.Handle, 100), el hilo principal esperará un poco más, consumiendo menos ciclos de CPU.
Sin embargo, una mejor solución sería el uso de mensajes. Su aplicación inicia el hilo y luego pone todos los controles en modo deshabilitado. Luego, el subproceso se ejecuta y, cuando termina, use SendMessage o PostMessage en la ventana principal para notificarle que el subproceso se ha vuelto a realizar. Entonces su aplicación simplemente habilitará cada control (y cualquier otra cosa) nuevamente. Esto tiene la ventaja de que mantiene vivo el bucle de mensajes "natural" para la aplicación, en lugar de ejecutar su propio bucle de mensajes con esta solución.
Desafortunadamente, el método de mensaje tiene un inconveniente: si el hilo se cuelga, no se enviará ningún mensaje, por lo que un plan de respaldo sería práctico. Por ejemplo, agregando un control de temporizador a su forma principal que comprueba cada segundo si el hilo aún está activo. Si no, también activaría el formulario nuevamente, deshabilitándose nuevamente.

2

Estoy de acuerdo con la observación de Mason Wheeler, es mejor dejar el hilo principal para hacer su trabajo, pero sugeriría utilizar el evento OnTerminate en el hilo. Es más 'Delphi natural' y la lógica interna hace el bit PostMessage para ti. Como TThread no es un componente, no puede verlo en el inspector de objetos y tiene que escribir y adjuntar un manejador de eventos usted mismo. Se llama (¡en el hilo principal!) Después de que el hilo ha finalizado/terminado.

12

La clase VCL TThread tiene su propio método WaitFor() que bombea la cola de mensajes principal internamente cuando se le llama en el contexto del hilo principal:

MyThread.WaitFor; 
ShowMessage('i am done'); 
Cuestiones relacionadas