Simular multithreading
Implementação em Pascal
Hoje proponho a simulação de multithreading em Pascal. É certo que o resultado é algo rudimentar, mas torna-se imensamente útil em pequenos pormenores, por exemplo, estar um processo a decorrer enquanto se espera uma tecla premida por parte do utilizador.
Esta torna-se, então, uma daquelas situações em que o módulo (ou unit) CRT encaixa perfeitamente numa programação de boas práticas e não em embelezamento exagerado e com um toque de non-sense.
O princípio é este: enquanto uma tecla não for premida, realizar um conjunto de acções.
Em "pascalês":
repeat
while not KeyPressed do begin
// Acções a realizar
delay(10);
end;
until (ReadKey = #13);
Note-se que as acções a realizar não devem demorar séculos a decorrer, se não o utilizador prime a tecla e tem de esperar uma eternidade para que seja assumida.
O delay de 10 milissegundos evita que o ciclo esteja sempre em execução, o que consome recursos, em especial do processador - em média, sem o delay, a CPU tem uma utilização entre 20 a 40% - não é agradável ouvir a ventoinha que nem um avião, certo? :-D
Neste caso, a tecla que se espera é a #13, ou seja, o Enter.
Se a acção a realizar é praticamemente instantânea, então o delay pode ser de 50 milissegundos. Porquê? O ser humano tem uma visão com uma frequência de 20fps, ou seja, os olhos captam 20 imagens por segundo. Sendo um segundo 1000 milissegundos, 1000ms / 20fps = 50ms. Assim, o utilizador prime a tecla e, apesar dos 50ms de delay, vai-lhe dar a sensação de que foi instantâneo.
E voilá, um multi-threading rudimentar, que poupa recursos ao computador, e parece instantâneo ao utilizador final.
Implementação em Delphi
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, Classes;
type
TTeste = class(TThread)
protected
procedure Execute; override;
end;
var
i:integer;
Teste:TTeste;
procedure TTeste.Execute;
var
i:integer;
begin
NameThreadForDebugging('ThreadTeste');
for i := 1 to 1000 do
begin
writeln('T2: ',i);
sleep(10);
end;
end;
begin // 1ª thread é iniciada, automaticamente com o programa principal
try
Teste:=TTeste.Create; // 2ª Thread é iniciada, o código de TTeste.Execute é executado
for i := 1 to 1000 do // Continuação do código da 1ª Thread
begin
writeln('T1: ',i,' = ',chr(i mod 26));
sleep(10);
end;
Teste.Destroy; // Libertada a 2ª Thread
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Writeln('Enter para terminar. . .');
Readln;
end. // Fim da 1ª Thread, juntamente com o fim do programa