multithreading - ¿Puedo mover Delphi TThread.Synchronize() localmente a un formulario VCL para ser llamado desde un hilo principal o trabajador?
thread-safety anonymous-methods (1)
La documentación dice:
Advertencia: no llame a Synchronize desde el hilo principal. Esto puede causar un ciclo infinito.
Creo que la documentación es simplemente incorrecta. La implementación en XE8 verifica si el hilo actual es el hilo principal. Si es así, el método se ejecuta directamente.
No se requiere bloqueo en ReceiveNotification
porque la llamada a GetSomeStringFunction
siempre se realiza en el hilo principal.
Estoy usando CreateAnonymousThread para una tarea de trabajo, y cuando comencé con ella utilicé Synchronize en toda la declaración según ejemplos documentados, por ejemplo:
procedure Txxx.RunWorker;
begin
FExecutionThread := TThread.CreateAnonymousThread(procedure ()
begin
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
// Here before worker stuff
NotifyBeforeWorkerStuff;
end);
// Do worker stuff
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
// Here after worker stuff
NotifyAfterWorkerStuff;
end);
end);
FExecutionThread.Start;
end;
end;
Como puede ver, desde este hilo, lanzo notificaciones de eventos a varias partes de mi aplicación, incluidos los formularios VCL (NotifyBeforeWorkerStuff, etc.). Más tarde, vi que podía mover Synchronize () más localmente a cada formulario VCL cerca del punto que realmente lo requería para actualizar los controles VCL (no seguros):
procedure TSomeVCLForm.ReceiveNotification;
begin
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
Label1.Caption := GetSomeStringFunction;
end);
end;
El hilo de trabajo se vuelve más simple siempre que yo viva con las notificaciones de subprocesos principales o de trabajo:
procedure Txxx.RunWorker;
begin
FExecutionThread := TThread.CreateAnonymousThread(procedure ()
begin
NotifyBeforeWorkerStuff;
// Do worker stuff
NotifyAfterWorkerStuff;
end);
FExecutionThread.Start;
end;
Tengo varias preguntas sobre si esto es correcto:
- Mis notificaciones pueden ser del hilo de trabajo pero también del hilo principal (por ejemplo, derivado de presionar un botón). Por lo tanto, cuando se llama a ''ReceiveNotification'' en un formulario VCL desde el hilo principal, ¿se permite llamar a TThread.Synchronize como se indicó anteriormente? Los documentos XE8 no implican, pero al comprobar System.Classes esto se ve bien y funciona bien.
- Dentro de ''ReceiveNotification'' cuando Label1.Caption recupera la cadena de GetSomeStringFunction, ¿es correcto que no hay absolutamente ninguna necesidad de bloquear dentro de esa función, incluso cuando la llamada proviene de un hilo de trabajo?
Gracias por cualquier consejo.