sexta-feira, 3 de outubro de 2008

SQL em segundo plano

Hoje resolvi falar de um assunto que muitas pessoas têm dúvidas: Threads. Mais especificamente, falarei sobre como rodar consultas ao banco de dados em segundo plano.

Às vezes, temos que efetuar uma consulta ao banco de dados que irá demorar muito ou até mesmo uma pequena consulta mas que o usuário não tenha que parar o que está fazendo para que ela seja realizada. Logo vem à nossa mente: "Vou fazer uma thread".

Embora possa parecer simples, algumas pessoas são pegas de surpresa com mensagens de erro estranhas, Access Violations etc, em virtude do uso indevido de threads para efetuar consultas ao banco de dados em segundo plano.

Threads

Segundo a Wikipédia:
"Thread, ou linha de execução em português, é uma forma de um processo dividir a si mesmo em duas ou mais tarefas que podem ser executadas simultaneamente.
"Uma linha de execução permite que o usuário de programa, por exemplo, utilize uma funcionalidade do ambiente enquanto outras linhas de execução realizam outros cálculos e operações.
"Em hardwares equipados com uma única CPU, cada linha de execução(Thread) é processada de forma aparentemente simultânea, pois a mudança entre uma linha e outra é feita de forma tão rápida que para o usuário isso está acontecendo paralelamente. Em hardwares com multiplos CPUs ou multi-cores as linhas de execução(Threads) podem ser realizadas realmente de forma simultânea"

Quando usar Threads

Você deve considerar o uso de Threads quando:

-Você precisa realizar múltiplas tarefas independentes;

-Sua aplicação roda em um sistema com múltiplos processadores ou um sistema multi-core(dual core, core 2 duo, quad core etc), desde que o sistema operacional dê suporte a eles;

-Você não quer que o usuário fique aguardando o fim de um processamento para continuar trabalhando, dentre outros motivos.

Problemas com Threads

No entanto, usar threads pode ser doloroso se você não souber exatamente o que está fazendo. Pode introduzir diversos bugs e mensagens misteriosas no teu sistema. Numa aplicação com um único Thread você tem o controle total sobre a ordem de execução de suas tarefas, além do acesso às variáveis globais. Numa aplicação multi-thread, por outro lado, você não tem esse tipo de controle. Deve estar ciente que, a qualquer momento, outro thread pode modificar o conteúdo de uma variável global e deve se proteger contra os conflitos que isso pode gerar.

Critical Section

O uso de TCriticalSection visa justamente coordenar o acesso aos recursos do sistema, servindo como uma espécie de semáforo que permite que apenas um thread tenha acesso a um determinado recurso em um determinado momento. Veja um exemplo de uso do TCriticalSection:



// Apartir de agora, somente uma thread por vez terá acesso a este bloco
MinhaSessaoCritica.Enter;
try
// Acesse o recurso compartilhado aqui.
// Normalmente, uma variável global.
// .....
finally
// Libera para que outras Threads possam entrar no mesmo bloco
MinhaSessaoCritica.Leave;
end;


Conexões com o Banco de Dados

Muita gente não sabe, mas para o correto funcionamento da aplicação multi-thread que acessa o banco de dados, é preciso que cada thread tenha a sua própria conexão com o banco. Caso contrário você terá problemas.

Fechando a aplicação

Outra coisa importante: Antes de fechar a sua aplicação deve se certificar que todos os threads estão terminados. Pode-se fazer isso por meio de uma variável global que seja incrementada a cada thread iniciado e decrementada para cada thread terminado. Se a variável estiver zerada, então pode-se fechar a aplicação. Caso contrário, devemos solicitar ao usuário que aguarde enquanto os processamentos são concluídos.

Mais uma vez, acho importante lembrar que para incrementar e decrementar uma variável global é preciso usar o TCriticalSection.

Synchronize()

O método Synchronize() executa uma chamada a um método especificado dentro do Thread principal. Portanto, não se deve fazer isto, se desejamos uma consulta em segundo plano:



procedure TQryThread.Execute;
begin
Synchronize(ConsultarBanco);
end;

procedure TQryThread.ConsultarBanco;
begin
SQLQuery1.Text := 'select .. from ...';
SQLQuery1.Open;
end;


Se fizermos isto, e o processamento for demorado, de nada vai adiantar estarmos usando uma Thread separada para efetuar a consulta.
O método Synchronize deve ser usado apenas se precisarmos atualizar alguns controles da VCL que façam parte do Thread Principal ou quando não tivermos certeza de que a chamada a um método é thread-safe.

Nenhum comentário:

 

web analytics software