2010-03-22 21 views
5

Tengo un sencillo programa Delphi en el que estoy trabajando, en el que intento usar threading para separar la funcionalidad del programa de su GUI, y para mantener la GUI sensible durante más tiempo tareas, etc. Básicamente, tengo un TThread 'controlador' y un TForm 'de vista'. La vista conoce el controlador del controlador, que utiliza para enviar los mensajes del controlador a través del PostThreadMessage. No he tenido ningún problema en el pasado con este tipo de modelo para formularios que no son la forma principal, pero por alguna razón, cuando intento utilizar este modelo para el formulario principal, el ciclo de mensajes del hilo simplemente se cierra.Thread Message Loop se bloquea en Delphi

Aquí está mi código para el bucle de mensajes hilos:

procedure TController.Execute; 
var 
    Msg : TMsg; 
begin 
    while not Terminated do begin 
    if (Integer(GetMessage(Msg, hwnd(0), 0, 0)) = -1) then begin 
     Synchronize(Terminate); 
    end; 

    TranslateMessage(Msg); 
    DispatchMessage(Msg); 

    case Msg.message of 
     // ...call different methods based on message 
    end; 
    end; 
end; 

Para configurar el controlador, hago esto:

Controller := TController.Create(true); // Create suspended 
Controller.FreeOnTerminate := True; 
Controller.Resume; 

para procesar mensajes del formulario principal, He intentado usar tanto Application.Run y el siguiente bucle (inmediatamente después de Controller.Resume)

while not Application.Terminated do begin 
    Application.ProcessMessages; 
end; 

Me he quedado atrapado aquí, cualquier ayuda sería muy apreciada.

+1

Bienvenido a Stack Overflow, erikjw! Espero que encuentres una buena respuesta. Nota rápida, sin embargo. Hace que su código sea más difícil de leer cuando coloca 'begin' en la misma línea que' do' o 'then' antes. Eso se considera un buen estilo en C, pero en Delphi la mayoría de nosotros prefiere ponerlo en su propia línea para que podamos alinear los pares 'begin' y' end' visualmente. –

+0

Gracias por todas las respuestas hasta el momento. He probado cada uno de ellos por separado, así como algunas combinaciones diferentes, y todavía tengo problemas. Cuando hago una depuración y paso por el código en 'TController.Execute', tan pronto como paso por' GetMessage', pase lo que pase como el hwnd, simplemente no sigue el ciclo. No ejecuta ninguna declaración después del ciclo, simplemente se detiene inexplicablemente. Y lo que es aún más confuso es que no veo ninguna indicación de que el hilo en sí haya muerto realmente. –

+0

¿Has intentado eliminar 'Synchronize()'? Si no se ejecuta ningún bucle de mensaje, puede fallar. Además, ¿qué versión de Delphi estás usando? – Nat

Respuesta

3

He probado su código básicamente como está y funcionó bien. Intente agregar una llamada a GetLastError después de que GetMessage devuelva -1 para ver cuál es el problema.

No está completamente claro desde el código si está creando ventanas dentro del hilo del controlador, pero si no, sugeriría pasar -1 en lugar de 0 como HWND a GetMessage, y eliminar las llamadas a TranslateMessage/DispatchMessage, ya que la declaración de caso que los sigue debe manejar cualquier mensaje que reciba.

Además, no necesita hacer "Sincronizar (Terminar)" en un error. Terminate simplemente establece el valor booleano "Terminado" en verdadero, por lo que no necesita sincronizarlo, y con la misma facilidad podría usar "Romper" para salir del ciclo con el mismo efecto.

0

¿Dónde está el "final" para el ciclo while? Creo que estás perdido y final. Así que tal vez (dependiendo del código real), estás atrapado en el while not Terminated do bucle sin fin en una sola declaración.

+0

Eso es malo, lo arreglaré en la pregunta: el ciclo abarca prácticamente toda la función. –