Skip to content

Subprocesos en segundo plano de forma segura

Subprocesos Delphi

La ejecución de tareas largas en segundo plano para mantener libre la interfaz de usuario (GUI) es uno de los objetivos de los múltiples subprocesos.

Un ejemplo práctico sería el siguiente:

procedure TForm1.Button1Click(Sender: TObject);
begin
  TThread.CreateAnonymousThread(
    procedure
    begin
      {Tarea_larga};
    end).Start;
end;

Muchos desarrolladores tenemos algún código como el anterior, ya sea para procesar datos o para realizar alguna conexión a algún servidor.

Pero que pasa si necesitamos mostrar algún resultado al usuario de esa “Tarea_larga”?.

Trabajar con la GUI desde un proceso en segundo plano, no es para nada seguro, por lo tanto hay que tener algún tipo de sincronización con el hilo principal, un ejemplo simple sería el siguiente:

procedure TForm1.Button1Click(Sender: TObject);
begin
  TThread.CreateAnonymousThread(
    procedure
    begin
      {Tarea_larga};
      TThread.Synchronize(nil,
        procedure
        begin
          {Mostrar_resultados};
        end);
    end).Start;
end;

Una vez que la ejecución ingresa al procedimiento dentro de TThread.Synchronize, se comienza a ejecutar dentro del contexto del hilo principal, por ende {Mostrar_resultados} debe ser lo mínimo e indispensable posible, ya que no se esta ejecutando en segundo plano, sino en el hilo principal como ya lo mencionamos.

Hay que tenerlo en cuenta ya que si {Mostrar_resultados} demora mucho tiempo en su ejecución, bloqueará la GUI de la misma manera de que si lo hubiésemos ejecutado en el hilo principal.

Que no hacer en subprocesos

En muchas consultas he visto que realizan la ejecución de procesos en segundo plano de la siguiente manera:

procedure TForm1.Button1Click(Sender: TObject);
begin
  TThread.CreateAnonymousThread(
    procedure
    begin
      TThread.Synchronize(nil,
        procedure
        begin
          {Tarea_larga};
          {Mostrar_resultados};
        end);
    end).Start;
end;

El ejemplo anterior es un error muy común cuando no se conoce con exactitud el funcionamiento de los subprocesos en segundo plano.

Lo que realiza este código es ejecutar {Tarea_larga} y {Mostrar_resultados} en el bloque de sincronización, o sea en el hilo principal y NO en segundo plano como debería.

Sería lo mismo que hacerlo de la siguiente manera:

procedure TForm1.Button1Click(Sender: TObject);
begin
  {Tarea_larga};
  {Mostrar_resultados};
end;

Ahora ya sabéis como se codifica un subproceso o ejecución en segundo plano para que no se nos bloquee nuestra App.