Execução Paralela com TTasks em Delphi

Execução Paralela com TTasks em Delphi
Tarefas paralelas.

Introdução

Nesse post iremos abordar sobre a execução paralela com TTasks em Delphi. A sua importância e exemplos práticos.

A execução paralela é uma técnica crucial em programação moderna, especialmente quando se lida com operações demoradas ou quando se deseja melhorar a responsividade de aplicações. Em Delphi, a classe TTask fornece uma maneira fácil e eficiente de executar múltiplas tarefas em paralelo. Neste artigo, exploraremos como usar TTask para executar tarefas paralelas e como gerenciar tarefas concorrentes de maneira eficaz.

Executando Múltiplas Tarefas em Paralelo

Introdução à Classe TTask

TTask é uma classe da biblioteca System.Threading que permite executar código em threads separadas. A principal vantagem de usar TTask é que ela simplifica o gerenciamento de threads, proporcionando uma interface de alto nível para a programação assíncrona.

Exemplo Básico de Execução Paralela

Vamos começar com um exemplo simples que demonstra como criar e executar múltiplas tarefas em paralelo.

Passo 1: Configurando o Projeto

  1. Abra o Delphi e crie um novo projeto VCL.
  2. Adicione um botão (TButton) e uma caixa de texto (TMemo) ao formulário principal.
  3. Na seção uses do formulário principal, adicione System.Threading.

Passo 2: Implementando o Código

uses
  System.SysUtils, System.Classes, System.Threading, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    StartButton: TButton;
    Memo1: TMemo;
    procedure StartButtonClick(Sender: TObject);
  private
    procedure Log(const Msg: string);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Log(const Msg: string);
begin
  TThread.Synchronize(nil,
    procedure
    begin
      Memo1.Lines.Add(Msg);
    end);
end;

procedure TForm1.StartButtonClick(Sender: TObject);
var
  Task1, Task2, Task3: ITask;
begin
  Task1 := TTask.Create(
    procedure
    begin
      Log('Task 1 iniciada');
      Sleep(2000); // Simula um trabalho de 2 segundos
      Log('Task 1 concluída');
    end);

  Task2 := TTask.Create(
    procedure
    begin
      Log('Task 2 iniciada');
      Sleep(3000); // Simula um trabalho de 3 segundos
      Log('Task 2 concluída');
    end);

  Task3 := TTask.Create(
    procedure
    begin
      Log('Task 3 iniciada');
      Sleep(1000); // Simula um trabalho de 1 segundo
      Log('Task 3 concluída');
    end);

  Task1.Start;
  Task2.Start;
  Task3.Start;
end;

end.

Explicação do Código

  1. Log: Este método utiliza TThread.Synchronize para garantir que as atualizações no componente Memo1 ocorram na thread principal, evitando problemas de concorrência.
  2. StartButtonClick: Este método cria três tarefas (Task1, Task2, Task3), cada uma simulando uma operação de duração diferente. As tarefas são iniciadas em paralelo com Start.

Veja abaixo a ilustração do projeto:

Execução Paralela com TTasks em Delphi
Ilustração do projeto.

Código fonte do exemplo

Você pode fazer o download do exemplo do projeto através do repositório do github:

https://github.com/Gisele-de-Melo/Execucao_Paralela_TTask

Benefícios da Execução Paralela

A execução paralela permite que múltiplas operações sejam executadas simultaneamente, melhorando a eficiência e a responsividade da aplicação. Em vez de executar tarefas de forma sequencial, podemos aproveitar os recursos de hardware modernos, como múltiplos núcleos de CPU, para reduzir o tempo total de execução.

Gerenciamento de Tarefas Concorrentes

Sincronização e Comunicação entre Tarefas (TTask)

Quando múltiplas tarefas acessam recursos compartilhados, é crucial gerenciar a sincronização para evitar condições de corrida e outros problemas de concorrência. Em Delphi, podemos usar objetos de sincronização como TCriticalSection e TEvent.

Exemplo de Sincronização

Vamos expandir o exemplo anterior para incluir sincronização entre tarefas.

Passo 1: Configurando o Projeto

  1. Abra o Delphi e crie um novo projeto VCL.
  2. Adicione um botão (TButton) e uma caixa de texto (TMemo) ao formulário principal.
  3. Na seção uses do formulário principal, adicione System.Threading e System.SyncObjs.

Passo 2: Implementando o Código

uses
  System.SysUtils, System.Classes, System.Threading, System.SyncObjs, Vcl.Forms, Vcl.Controls, 
  Vcl.StdCtrls, Vcl.Dialogs;

type
  TForm1 = class(TForm)
    StartButton: TButton;
    Memo1: TMemo;
    procedure StartButtonClick(Sender: TObject);
  private
    CriticalSection: TCriticalSection;
    procedure Log(const Msg: string);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  CriticalSection := TCriticalSection.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  CriticalSection.Free;
end;

procedure TForm1.Log(const Msg: string);
begin
  TThread.Synchronize(nil,
    procedure
    begin
      Memo1.Lines.Add(Msg);
    end);
end;

procedure TForm1.StartButtonClick(Sender: TObject);
var
  Task1, Task2, Task3: ITask;

begin
  try
    Task1 := TTask.Create(
      procedure
      begin
        CriticalSection.Enter;
        try
          Log('Task 1 iniciada');
          Sleep(2000); // Simula um trabalho de 2 segundos
          Log('Task 1 concluída');
        finally
          CriticalSection.Leave;
        end;
      end);

    Task2 := TTask.Create(
      procedure
      begin
        CriticalSection.Enter;
        try
          Log('Task 2 iniciada');
          Sleep(3000); // Simula um trabalho de 3 segundos
          Log('Task 2 concluída');
        finally
          CriticalSection.Leave;
        end;
      end);

    Task3 := TTask.Create(
      procedure
      begin
        CriticalSection.Enter;
        try
          Log('Task 3 iniciada');
          Sleep(1000); // Simula um trabalho de 1 segundo
          Log('Task 3 concluída');
        finally
          CriticalSection.Leave;
        end;
      end);

    Task1.Start;
    Task2.Start;
    Task3.Start;
  except
    on E: exception do
      ShowMessage(E.Message);
  end;
end;

end.

Explicação do Código

  1. CriticalSection: A variável CriticalSection é usada para garantir que apenas uma tarefa por vez possa acessar o código dentro do bloco CriticalSection.Enter e CriticalSection.Leave.
  2. Sincronização: Cada tarefa entra na seção crítica antes de executar e sai da seção crítica após concluir. Isso garante que as tarefas não acessem simultaneamente o recurso compartilhado (no caso, o componente Memo1).

Veja abaixo a ilustração do projeto:

Execução Paralela com TTasks em Delphi
Ilustração do projeto.

Código fonte do exemplo

Você pode fazer o download do exemplo do projeto através do repositório do github:

https://github.com/Gisele-de-Melo/Sincronizacao_Comunicacao_TTask

Benefícios do Gerenciamento de Tarefas Concorrentes

O gerenciamento adequado de tarefas concorrentes é essencial para evitar problemas de concorrência, como condições de corrida e deadlocks. Utilizando objetos de sincronização, podemos garantir que as tarefas compartilhem recursos de maneira segura e eficiente.

Conclusão

A execução paralela com TTasks em Delphi é uma técnica poderosa para melhorar a eficiência e a responsividade das aplicações. Ao utilizar TTask, podemos executar múltiplas operações em paralelo de maneira simples e eficaz. No entanto, é crucial gerenciar a sincronização entre tarefas concorrentes para evitar problemas de concorrência.

Com as técnicas apresentadas neste artigo, você pode começar a implementar execução paralela em suas aplicações Delphi, aproveitando ao máximo os recursos de hardware disponíveis e melhorando a experiência do usuário.

Posts Relacionados

Livros + e-books

Delphi para Android e iOS

codedelphi.com
codedelphi.com

Delphi Start

codedelphi.com

Programando em Delphi XE

Aprenda programar Delphi

Banco de Dados RAD Delphi

Delphi Programming Projects

Deixe um comentário