Quando se trabalha com processos paralelos o isolamento de memória com acesso comum a processos diferentes é fundamental.

Uma opção é implementar utilizando  TThreadList que mantem o controle da lista bloqueando ou liberando quando precisa acessar a área de armazenamento sem especialidades do TStringList .

De outro lado o TStringList não é threadsafe o que motiva a reescrever as funcionalidades para compartilhamento da lista entre os processos…   Ver Classes TThreadSafe….

[code lang=”pascal”]
TThreadSafeStringList
// public
procedure Clear;
function Count: integer;
function IndexOf(AText: string): integer;
function IndexOfName(AText: string): integer;
procedure Add(AText: string; ADupl: boolean = true);
procedure Delete(AIndex: integer);
procedure Remove(AText: string);
function LockList: TStringList;
procedure UnlockList; inline;
property Items[AIndex: integer]: string read Getitems write Setitems;
property Delimiter: Char read GetDelimiter write SetDelimiter;
property DelimitedText: string read GetDelimitedText write SetDelimitedText;
function Text: string;
property CommaText: string read GetCommaText write SetCommaText;
property QuoteChar: Char read GetQuoteChar write SetQuoteChar;
procedure Assing(AStrings: TStrings);
procedure AssingTo(AStrings: TStrings);
procedure AddTo(AStrings: TStrings);
property Values[AName: string]: String read GetValues write SetValues;
property Names[AIndex: integer]: String read GetNames write SetNames;
[/code]

Exemplo de como utilizar as lista compartilhando em Threads diferentes mantendo o controle do acesso a lista… [Codigo]

[code lang=”pascal”]
{$R *.fmx}

procedure TForm2.Button1Click(Sender: TObject);
var
x: integer;
begin
strList.Clear;
// Thread 1
tthread.CreateAnonymousThread(
procedure
var
x: integer;
begin
for x := 0 to random(1000) do
begin
strList.Add(‘X’ + intToStr(x));
tthread.Sleep(random(10));
end;
strList.Add(‘X-FIM’);

tthread.Queue(nil,
procedure
begin
strList.AssingTo(Memo1.lines);
end);

end).start;

// Thread 2
tthread.CreateAnonymousThread(
procedure
var
x: integer;
begin
for x := 0 to random(1000) do
begin
strList.Add(‘Z’ + intToStr(x));
tthread.Sleep(random(10));
end;
strList.Add(‘Z-FIM’);

tthread.Queue(nil,
procedure
begin
strList.AssingTo(Memo1.lines);
end);

end).start;

end;

procedure TForm2.FormCreate(Sender: TObject);
begin
strList := TThreadSafeStringList.create;

end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
strList.free;
end;

[/code]

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]