2012-05-21 7 views
12

Si el código Delphi se escribió con sincronización para serializar el acceso al hilo VCL principal, pero este código se usa en una aplicación que no es VCL, ¿se sincronizará con el hilo principal de la aplicación o simplemente no tendrá ningún efecto?¿Es peligroso usar la sincronización en una aplicación que no sea VCL?


Ejemplo:

procedure TMyThread.Execute; 
begin 

    // ... other code 

    Synchronize(SomeMethod); 

    // ... 

end; 

Asumamos

  • es una aplicación no VCL que tiene un hilo principal, que se ejecuta en un bucle sin fin (o hasta su terminación)
  • el hilo principal no llama al CheckSynchronize directamente o en un controlador WakeMainThread
  • un subproceso secundario se ejecuta y ejecuta Sincronizar (SomeMethod) como en el ejemplo anterior

¿Se bloqueará el subproceso en la línea Sincronizar (SomeMethod)?

+0

¿La aplicación sin VCL está bajo su control? Si no, entonces no puede usar 'Sincronizar'. –

+0

@DavidHeffernan Puedo imaginar un 'synchronize (CallEventHandler)' en una biblioteca donde puedo asignar un método al controlador de eventos. El compilador no se quejará si no es una aplicación de VCL. – mjn

+0

Por supuesto, el compilador no se quejará. No tiene nada que ver con la sintaxis del comando o el alcance de los identificadores. Pero @David está equivocado al decir que no puedes usar 'Sincronizar'. Puedes usarlo todo lo que quieras. Solo tiene que publicar que lo está usando para que el consumidor de su biblioteca sepa usar 'CheckSynchronize'. Sin embargo, no sé qué sucederá si el anfitrión no cumple con su parte del contrato. Siéntase libre de escribir un programa de prueba e informar sus propios resultados aquí. –

Respuesta

9

TThread proporciona instalaciones para programas que no son VCL para comprobar la cola de sincronización, por lo que pueden continuar utilizando bibliotecas multiproceso que esperan sincronizar sus métodos. Esto se describe en el documentation for CheckSynchronize. Recuerde que es tarea de la aplicación verificar la cola, no la de su biblioteca.

Siempre que la aplicación cumpla con su parte del contrato, su uso de Synchronize debería estar bien. Si no lo hace, entonces su programa no funcionará correctamente, pero no sé qué síntomas exactos esperar. Colgar ciertamente suena plausible.

+0

ver mi edición: el DocWiki no está nada claro, se lee como si la asignación de WakeMainThread y la invocación de CheckSynchronize fuera una optimización opcional. – mjn

+0

La asignación de 'WakeMainThread' es la optimización. Se espera que el hilo principal se active por sí solo * eventualmente * y observe las nuevas tareas sincronizadas para realizar, pero 'WakeMainThread', si se proporciona, indica al hilo principal que se active * inmediatamente *. Se reduce la latencia. –

+0

Lo siento por eliminar mi comentario anterior! He leído en su comentario 'No sé qué sucede si el anfitrión no respeta su parte del contrato, sin embargo. 'y luego lo borré suponiendo que no es tan fácil responder – mjn

6

¿Es peligroso utilizar la sincronización en una aplicación que no sea VCL?

Sí es peligroso. Si el hilo principal no está llamando al CheckSynchronize, entonces Synchronize dará como resultado un interbloqueo.

Asumamos

  • es una aplicación no VCL que tiene un hilo principal, que se ejecuta en un bucle sin fin (o hasta su terminación)
  • el hilo principal no llama CheckSynchronize directamente o en un manejador de WakeMainThread
  • una secundarias ejecuta el subproceso y ejecuta Synchronize(SomeMethod) como en el ejemplo anterior

¿Se colgará el hilo en la línea Synchronize(SomeMethod)?

La llamada a Synchronize bloqueará el hilo de fondo hasta que el hilo principal llame al CheckSynchronize. Por lo tanto, si el hilo principal nunca llama a CheckSynchronize, el hilo de fondo se bloqueará indefinidamente.

El programa siguiente ilustra esto:

program TheBigSleep; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils, Classes, Windows; 

type 
    TMyThread = class(TThread) 
    protected 
    procedure Execute; override; 
    end; 

procedure TMyThread.Execute; 
begin 
    Synchronize(SysUtils.Beep); 
end; 

begin 
    with TMyThread.Create do 
    WaitForSingleObject(Handle, INFINITE); 
    //don't call WaitFor since that, in turn, calls CheckSynchronize 
end. 
+3

+1, y sobre 'Sincronizar', nunca lo use. El hilo no debe depender de lo que está fuera de su alcance. Es mejor utilizar llamadas no bloqueantes como 'PostMessage' o' TThread.Queue'. Vea la respuesta de [mghie's] (http://stackoverflow.com/users/30568/mghie) a [¿Es mejor usar TThread's "Sincronizar" o usar Mensajes de ventana para IPC entre el hilo principal y secundario?] (Http: // stackoverflow .com/a/1806947/576719) para un resumen. –

1

Puesto que usted está poniendo el código de Delphi en una biblioteca para otras aplicaciones que utilizan, yo no aconsejaría usando Synchronize() en absoluto, ya que el hilo no tiene un concepto de lo está sucediendo fuera de sí mismo. Una mejor opción es hacer que el hilo exhiba un evento de devolución de llamada que el hilo pueda invocar en su propio contexto cuando sea necesario, y luego dejar que la aplicación proporcione un manejador de función de devolución de llamada que decida la mejor manera de sincronizar con el hilo principal de la aplicación según sea necesario.

Cuestiones relacionadas