Executar uma query em segundo plano (em paralelo) não …é difícil de fazer, o seu controle é que
pode ser mais complexo.
Para executar em segundo plano basta:

[code lang=”pascal”]
TThread.CreateAnonymousThread(procedure
begin
ALQuery1.sql.Text := ‘….’;
ALQuery1.Open;
end).Start;
[/code]

ou

[code lang=”pascal”]
TThread.CreateAnonymousThread(
procedure
var i:integer;
begin
for I := 0 to 10 do
begin
// faz alguma coisa…
AlQuery1.execSQL;
end;
end).Start;
[/code]

Um pensamento simplista é você criar uma conexão para cada QUERY em separado. Se você tem
um CONNECTION isolado para UMA QUERY, então é possível executá-la em paralelo dentro de
uma nova Thread;

Algumas idéias onde pode utilizar o processo em paralelo:
– quando precisa registrar um log em uma tabela;
– se for possível adiantar um SELECT que será utilizado mais a frente;
– se precisa rodar um loop que não tem dependência com os próximos passos da sequencia do
código;
– quando precisa fazer um somatório de dados na tabela para mostrar o seu valor na janela…. e
liberar o usuário para continuar fazendo outras coisas.
As vezes você pode por um SELECT em paralelo e disparar outra sequencia de código… e mais
adiante aguardar o primeiro SELECT concluir… para depois então continuar…. Este é assunto para
outro POST para tratar de TTASK.

Interfaces disponíveis através de TTASK que se encontra na unit System.Threading…
Enquanto ITask aguarda uma chamada x.start; para iniciar o processamento em uma thread
própria… o IFuture já inicia o processamento de imediato e aceita aguardar uma resposta após o
término de execução.

Exemplo ITask: (aguarda start para iniciar)
[code lang=”pascal”]
tsk := TTask.create( procedure begin
// código a ser executado
end);
tsk.start;
//pode ou não pedir para aguardar conclusão:
tsk.wait( 1000000);</pre>
[/code]

Exemplo IFuture: (inicia assim que for criado)
[code lang=”pascal”]
tsk = TTask.Future:boolean(
function:boolean
begin
// código…..
result := true; // resposta para o processamento
end);

resposta := tsk.value; // aguarda a thread terminal e pega o resultado
[/code]

Se precisar retornar mais de um valor, pode usar um RECORD:

[code lang=”pascal”]
TPessoa = record
nome:string;
idade:integer;
end;

tsk = TTask.Future:TPessoa(
function:TPessoa
begin
// código…..
result.nome := ‘Nome’; // resposta para o processamento
result.idade := 18;
end);

resposta := tsk.value; // aguarda a thread terminar e pega o resultado
if resposta.idade&gt;18 then
xxxxx
[/code]

Na versão XE7 foi incorporado ao Delphi o conceito de processamento paralelo. Antes já era
possível fazer algo parecido utilizando bibliotecas de terceiros
[http://www.omnithreadlibrary.com/index.htm http://andy.jgknet.de/blog/bugfix-units/asynccalls-
29-asynchronous-function-calls/].
Para tentar simplificar o conceito, diz paralelo quando consegue executar dois ou mais processos ao
mesmo tempo, daí o nome “paralelo”.

Exemplo utilizando TTask:

[code lang=”pascal”]
var
tsk: array [0 .. 2] of ITask;
i, n: integer;
begin
tsk[0] := TTask.create(
procedure
begin
TThread.Queue(nil, procedure
begin
caption := ‘xxx’; // sincronizar a atualização da janela.
end);
end);
tsk[0].Start; // inicia o processamento antes de criar as TTask seguintes
tsk[2] := TTask.create(
procedure
var
k: integer;
begin
i := 1;
sleep(1000);
for k := 0 to 10000 do
inc(i);
end);
tsk[1] := TTask.create(
procedure
var
k: integer;
begin
n := n;
for k := 0 to 1000 do
inc(n);
add( ‘N’);
end);
tsk[2].Start; // inicia o processamento
tsk[1].Start;
TTask.WaitforAll(tsk); // quando quer aguardar o termino de todas as TTasks
[/code]

Houve um tempo que executar tarefas em “background” era um tortura.
Com a evolução de hardware e software, fazer uso de computação paralela passou a ser tão
fácil quanto um desafio em resistir ao seu uso.

Introduzida na versão XE7, um “thread” passou a rodar considerando o balanceamento entre
os processadores presentes na unidade de processamento.

Associar o uso de métodos anônimos facilitou em muito todo o trabalho:
[code lang=”pascal”]
TThread.CreateAnonymousThread(
procedure begin
// execute aqui o seu código
….
// se precisar sincronizar atualização de
// controles da janela
TThread.Queue(nil,
procedure begin
// aqui deve incluir a atualização
// dos controles da janela;
// ex: label1.caption := ‘texto’;
end);
end).Start;
[/code]

A introdução de Class Helper no delphi ajudou o desenvolvedor a incluir novas
funcionalidades nas classes nativas do delphi – você tem uma idéia de um
recursos dos sonhos e gostaria de implementar lá na classe base, use Class
Helper.

Extendendo o TDataset:
[code lang=”pascal”]
TDatasetHelper = class helper for TDataset
public
procedure Run(AProc:TProc<TDataset>);
end;

procedure TDatasetHelper.Run(AProc: TProc<TDataset>);
begin // executa em um thread separada
TThread.CreateAnonymousThread(
procedure begin
if assigned(AProc) then
AProc(self);
end
).Start;
end;
[/code]
O exemplo implementa a capacidade de uso da “procedure” RUN(…) por
qualquer classe com herança de TDataset.

Trabalhando com o novo procedimento:

O procedimento RUN por finalidade executar em um processo paralelo (uma
nova TThread) a rotina que estiver implementando no TProc.
[code lang=”pascal”]
var total:double;
begin
query1.run(
procedure (ds:TDataset) // rotina a executar em paralelo.
begin
ds.first;
while ds.eof=false do
begin
total := total + xxxxx;
ds.next;
end;
end);
end;

[/code]

O Firebird aceita usar o Order By indicando o nome da coluna (o mais conhecido), o número da coluna ou pelo apelido da coluna.

Exemplo usando o nome da coluna:
[code lang=”SQL”]
select
codigo, nome, preco, (preco * 1.05) precoPrazo
from fb_prod
order by nome Rows 10
[/code]

Exemplo usando o número da coluna
[code lang=”SQL”]
select
codigo, nome, preco, (preco * 1.05) precoPrazo
from fb_prod
order by 4 Rows 10
[/code]

Exemplo usando o apelido da coluna:
[code lang=”SQL”]
select
codigo, nome, preco, (preco * 1.05) precoPrazo
from fb_prod
order by precoPrazo Rows 10
[/code]

O Firebird tem duas formas diferentes de limitar o número de linhas:

First/Skip   ou

Rows/To    (mais nova)

Exemplo:

select codigo, nome from clientes Rows 10 To 15

Retorna as linhas de número 10 até a linha 15 (primeira linha=1)

Se rows>0 sem indicar o To retorna as N linhas a partir do primeiro registro.

Se rows=0 não retorna nenhuma linha.

Se rows <0 vai gerar uma exceção.