[usa LogEvents]
Tenho uma quantidade de produtos relativamente grande que requer processamento de custos de produção envolvendo custo de matérias primas, mão-de-obra e outros custos vinculado a célula de produção.

A modelagem prevê que uma ficha de produção pode conter outras fichas formando uma lista de dependências dos processos o que gera processamento recursivo de dependências.

Como se pode imaginar, não é um processamento sequenciado tão simples e pode ser demorado em face a profundidade da arvore de dependência que um produto pode exigir.

Então repensando os processos, o desafio passou exigir processamento em paralelo das fichas de tal forma que fosse possível processar uma quantidade de produtos ao mesmo tempo e aproveitando melhor os recursos da máquina;

Neste cenário, saber qual o estágio de processamento de cada ficha e o onde se encontra o cálculo passou a ser requisito de interação com usuário;

Para executar vamos utilizar da biblioteca de processamento em paralelo do Delphi (introduzido no XE7, no exemplo usamos Berlin).

Passos:

  • Isolar as conexões de banco de dados para trata-las individualmente por Task;
  • Criar infraestrutura de comunicação entre o processamento e feedback com usuário;
  • Tratar a sincronização de informações geradas pelas várias TTasks em andamento informando a janela de progresso do usuário;
imagem_janela
Tendo em mente que o controle possa ser utilizado em outras aplicações, o uso de um procedimento ANONIMOUS me parece bastante resistente a diversidade de códigos a que poderá vir a ser utilizado.
Veja como ficou o exemplo de execução:

[code lang=”pascal”]

procedure TForm8.Button1Click(Sender: TObject);
var
LProgr: IProgressEvents;
i: integer;
begin
// inicializa a janela de progresso
LProgr := TProgressEvents.new;
LProgr.max := 100; // opcional: marca o número máximo itens
LProgr.MaxThreads := SpinEdit1.Value ; // indica o número máximo de threads em paralelo
LProgr.CanCancel := true; :// marca se pode cancelar a operação

for i := 1 to 100 do
begin // loop de demonstração – simulando uma lista de processos
LProgr.Text := ‘Produto: ‘ + intToStr(i); // texto livre

// onde as coisas acontecem…..
// adiciona o processo a ser executado e aponta o método anonimous as ser executado pela TTask
LProgr.add(i, ‘Produto: ‘ + intToStr(i), // processo a executar
procedure(x: integer)
var
n: integer;
msg: string;
begin
msg := ‘Produto: ‘ + intToStr(x); // processo em execução
LogEvents.DoProgress(self, 0, etStarting, msg); // notifica que o processo foi iniciado
n := Random(10000);

sleep(n);
LogEvents.DoProgress(self, 0, etWorking, msg); // notifica que esta em execução
// executa o código de calculo … aqui…
n := Random(10000);
if LProgr.Terminated then exit; // checa se o usuario cancelou a operação
sleep(n);
end);
if LProgr.Terminated then
break;
end;
LogEvents.DoProgress(self, 0, etAllFinished, ”); // sinaliza que todas os processo foram completados.
end;

[/code]

Código fonte com o Exemplo e classes que implementam a janela de monitoramento do progresso de cada thread.