Threading & Multi-Threading
Threading patterns in Delphi — TThread, TTask, TParallel, Synchronize, Queue, thread-safety, Producer-Consumer, pools, cancellation and debugging
Install / Use
npx skills add delphicleancode/delphi-spec-kit --skill threadingInstalls into whichever agent you are using.
Gemini Rules
Gemini CLI config
Quality Score
Category
Development & EngineeringSupported Platforms
Tags
Our assessment of Threading & Multi-Threading
Threading & Multi-Threading scores 76/100 on our quality scale, 1639th of 2,717 Development & Engineering skills we index.
Its Gemini Rules is 22 KB long, well organised into 34 sections with 22 code examples: a thorough specification that gives an agent plenty to work with.
It has no GitHub stars yet, so there is no community track record; judge it on its content.
Maintenance, license and trust
- The repository was last updated about 6 months ago. That is recent enough to be usable, but agent tooling moves fast, so check the instructions against your agent's current version.
- Our last check on 2026-09-24 found the source still online.
- No license is declared. By default that means all rights are reserved: you can read it, but reusing or redistributing it is not clearly permitted. Ask the author before building on it commercially.
- Its trust signals score 74/100, with 3 cautions from licensing, adoption, age or documentation. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
Safety scan
No issues foundOur scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful.
AI review by kimi-k2.7-code on 2026-09-24. Automated pattern scan on 2026-09-24. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.
Threading & Multi-Threading compared with similar skills
All 4 of these similar skills score higher than Threading & Multi-Threading; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| Threading & Multi-Threading (this skill)by delphicleancode | 76 | 0 | 6mo ago | Gemini Rules |
| ai-job-searchby MadsLorentzen | 100 | 44.1k | today | CLAUDE.md |
| claude-howtoby luongnv89 | 100 | 41.7k | 1d ago | CLAUDE.md |
| algorithmic-artby anthropics | 100 | 177.9k | 5d ago | SKILL.md |
| interview-meby addyosmani | 100 | 98.8k | 4d ago | SKILL.md |
Frequently asked questions
- How do I install Threading & Multi-Threading?
- Run
npx skills add delphicleancode/delphi-spec-kit. The install tabs above show the steps for each supported agent. - Which AI agents does Threading & Multi-Threading work with?
- It is written for Gemini CLI, as a Gemini Rules file. Other agents that read the same format can often use it too.
- Is Threading & Multi-Threading safe to use?
- Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful. It declares no license and scores 74/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is Threading & Multi-Threading still maintained?
- The repository was last updated about 6 months ago. That is recent enough to be usable, but agent tooling moves fast, so check the instructions against your agent's current version.
Skill content
View source on GitHubname: "Threading & Multi-Threading" description: "Threading patterns in Delphi — TThread, TTask, TParallel, Synchronize, Queue, thread-safety, Producer-Consumer, pools, cancellation and debugging"
Threading & Multi-Threading — Skill
Use this skill when working with threads, asynchronous tasks and parallelism in Delphi projects.
When to Use
- When performing time-consuming operations without blocking the UI (VCL/FMX)
- When implementing parallel data processing
- When creating servers/workers that process concurrent requests
- When synchronizing access to shared resources
- When managing thread pools and work queues
- By implementing graceful thread cancellation
Golden Rule of Threading in Delphi
NEVER access visual components (VCL/FMX) directly from a secondary thread. Use
TThread.SynchronizeorTThread.Queueto update the UI.
Available Approaches
| Approach | When to Use | Complexity |
|-----------|-------------|-------------|
| TThread | Full control, long-running threads | Average |
| TThread.CreateAnonymousThread | Simple, one-shot tasks | Low |
| TTask (PPL) | Modern parallelism, lightweight tasks | Low |
| TParallel.For (PPL) | Parallel loops in collections | Low |
| TFuture<T> (PPL) | Asynchronous result with return value | Low |
| TThreadPool | Reusable Thread Pool | Average |
| Dedicated thread (inheritance) | Permanent workers, servers, queues | High |
TThread — Classical Approach
Thread with Inheritance (Recommended for Workers)
type
/// <summary>
/// Worker thread para processamento em background.
/// Demonstra herança de TThread com cancelamento via Terminated.
/// </summary>
TDataProcessorThread = class(TThread)
private
FItems: TThreadList<string>;
FOnProgress: TProc<Integer, Integer>;
FOnComplete: TProc<Boolean>;
protected
procedure Execute; override;
public
constructor Create(AItems: TThreadList<string>);
property OnProgress: TProc<Integer, Integer> write FOnProgress;
property OnComplete: TProc<Boolean> write FOnComplete;
end;
constructor TDataProcessorThread.Create(AItems: TThreadList<string>);
begin
inherited Create(True); // Criar suspensa
FreeOnTerminate := True; // Auto-libera ao terminar
FItems := AItems;
end;
procedure TDataProcessorThread.Execute;
var
LList: TList<string>;
LTotal, I: Integer;
begin
try
LList := FItems.LockList;
try
LTotal := LList.Count;
finally
FItems.UnlockList;
end;
for I := 0 to LTotal - 1 do
begin
{ Verificar cancelamento em cada iteração }
if Terminated then
Exit;
{ Processar item }
ProcessItem(I);
{ Atualizar UI via Queue (não-bloqueante) }
if Assigned(FOnProgress) then
TThread.Queue(nil,
procedure
begin
FOnProgress(I + 1, LTotal);
end);
end;
{ Notificar conclusão na main thread }
if Assigned(FOnComplete) then
TThread.Queue(nil,
procedure
begin
FOnComplete(not Terminated);
end);
except
on E: Exception do
begin
TThread.Queue(nil,
procedure
begin
raise EThreadException.Create('Erro no processamento: ' + E.Message);
end);
end;
end;
end;
Use of Dedicated Thread
procedure TfrmMain.btnProcessClick(Sender: TObject);
var
LThread: TDataProcessorThread;
begin
LThread := TDataProcessorThread.Create(FSharedItems);
LThread.OnProgress :=
procedure(ACurrent, ATotal: Integer)
begin
pbrProgress.Max := ATotal;
pbrProgress.Position := ACurrent;
lblStatus.Caption := Format('Processando %d de %d...', [ACurrent, ATotal]);
end;
LThread.OnComplete :=
procedure(ASuccess: Boolean)
begin
if ASuccess then
ShowMessage('Concluído com sucesso!')
else
ShowMessage('Processamento cancelado.');
end;
LThread.Start; // Iniciar a thread
end;
procedure TfrmMain.btnCancelClick(Sender: TObject);
begin
{ Solicitar cancelamento gracioso }
if Assigned(FCurrentThread) then
FCurrentThread.Terminate;
end;
CreateAnonymousThread (Simple Tasks)
/// <summary>
/// Forma mais simples de executar código em background.
/// Ideal para one-shot tasks sem necessidade de controle avançado.
/// </summary>
procedure TfrmMain.LoadDataAsync;
begin
btnLoad.Enabled := False;
TThread.CreateAnonymousThread(
procedure
var
LData: TStringList;
begin
LData := TStringList.Create;
try
{ Trabalho pesado (thread secundária — OK!) }
LData.LoadFromFile('C:\dados\arquivo_grande.csv');
Sleep(2000); // Simular processamento
{ Atualizar UI (DEVE usar Synchronize ou Queue) }
TThread.Synchronize(nil,
procedure
begin
mmoOutput.Lines.Assign(LData);
btnLoad.Enabled := True;
lblStatus.Caption := Format('Carregados %d registros', [LData.Count]);
end);
finally
LData.Free;
end;
end
).Start;
end;
Synchronize vs Queue
| Method | Behavior | When to Use |
|--------|--------------|-------------|
| TThread.Synchronize | Blocking — waits for the main thread to process | When you need the UI result |
| TThread.Queue | Non-blocking — queue and continue | Progress, logs, visual updates |
{ Synchronize: BLOQUEIA a thread até a main thread processar }
TThread.Synchronize(nil,
procedure
begin
lblStatus.Caption := 'Processando...';
end);
// A thread só continua AQUI after que a main thread executou o código acima
{ Queue: NÃO BLOQUEIA — enfileira e continua imediatamente }
TThread.Queue(nil,
procedure
begin
lblStatus.Caption := 'Processando...';
end);
// A thread continua IMEDIATAMENTE, sem esperar a main thread
Recommendation: Prefer
Queuewhenever possible. UseSynchronizeonly when you need a result from the UI back in the thread.
PPL — Parallel Programming Library (System.Threading)
TTask — Light Tasks
uses
System.Threading;
/// <summary>
/// TTask é a forma moderna de executar tarefas em background.
/// Gerenciado automaticamente pelo pool de threads do sistema.
/// </summary>
procedure TfrmMain.ExecuteMultipleTasks;
var
LTask1, LTask2, LTask3: ITask;
begin
LTask1 := TTask.Create(
procedure
begin
{ Tarefa 1: Carregar dados do banco }
LoadCustomers;
end);
LTask2 := TTask.Create(
procedure
begin
{ Tarefa 2: Processar relatório }
GenerateReport;
end);
LTask3 := TTask.Create(
procedure
begin
{ Tarefa 3: Enviar emails }
SendPendingEmails;
end);
{ Iniciar todas as tarefas em paralelo }
LTask1.Start;
LTask2.Start;
LTask3.Start;
{ Aguardar todas completarem (com timeout) }
TTask.WaitForAll([LTask1, LTask2, LTask3], 30000); // 30s timeout
TThread.Queue(nil,
procedure
begin
ShowMessage('Todas as tarefas concluídas!');
end);
end;
TTask.Run — Direct Shortcut
{ Forma mais simples de executar em background via PPL }
TTask.Run(
procedure
begin
{ Código executado no ThreadPool }
PerformHeavyCalculation;
TThread.Queue(nil,
procedure
begin
lblResult.Caption := 'Cálculo concluído';
end);
end);
TParallel.For — Parallel Loops
uses
System.Threading,
System.SyncObjs;
/// <summary>
/// TParallel.For distribui iterations do loop entre múltiplas threads.
/// Ideal para processamento de coletions independentes.
/// </summary>
procedure TfrmMain.ProcessImagesParallel;
var
LFiles: TArray<string>;
LProcessed: Integer;
LLock: TCriticalSection;
begin
LFiles := TDirectory.GetFiles('C:\Images', '*.jpg');
LProcessed := 0;
LLock := TCriticalSection.Create;
try
TParallel.For(0, High(LFiles),
procedure(AIndex: Integer)
begin
{ Cada imagem processada em thread separada }
ResizeImage(LFiles[AIndex]);
{ Atualizar contador de forma thread-safe }
LLock.Enter;
try
Inc(LProcessed);
finally
LLock.Leave;
end;
end);
ShowMessage(Format('%d imagens processadas', [LProcessed]));
finally
LLock.Free;
end;
end;
⚠️ CAUTION: Each iteration of
TParallel.Forcan run on different threads. Shared variables MUST be protected withTCriticalSection,TMonitororTInterlocked.
TFuture<T> — Asynchronous Result
uses
System.Threading;
/// <summary>
/// TFuture executa uma tarefa e returns um valor quando pronto.
/// A leitura de .Value bloqueia até o resultado estar disponível.
/// </summary>
procedure TfrmMain.CalculateAsync;
var
LFuture: IFuture<Double>;
begin
LFuture := TFuture<Double>.Create(
function: Double
begin
{ Cálculo pesado em background }
Sleep(3000);
Result := CalculateComplexFormula(FInputData);
end);
LFuture.Start;
{ Fazer outras coisas enquanto o cálculo roda... }
PrepareReport;
{ Pegar o resultado (bloqueia SE ainda não terminou) }
ShowMessage(Format('Resultado: %.2f', [LFuture.Value]));
end;
Thread-Safety — Resource Protection
TCriticalSection
type
TThreadSafeCounter = class
private
FCount: Integer;
FLock: TCriticalSection;
public
constructor Create;
destructor Destroy; override;
procedure Increment;
procedure Decrement;
function GetValue: Integer;
end;
constructor TThreadSafeCounter.Create;
begin
inherited;
FLock := TCriticalSection.Create;
FCount := 0;
end;
destructor TThreadSafeCounter.Destroy;
begin
FLock.Free;
inherited;
end;
procedure TThreadSafeCounter.Increment;
begin
FLock.Enter;
try
Inc(FCount);
finally
FLock.Leave; // ALWAYS no finally!
end;
end;
function TThreadSafeCounter.GetValue: Integer;
begin
FLock.Enter;
try
Result := FCount;
finally
FLock.Leave;
end;
end;
TMonitor (Native Object Lock)
{ TMonitor usa o próprio objeto como lock — sem criar TCriticalSection }
procedure TThreadSafeList.AddItem(const AItem: string);
begin
TMonitor.Enter(FList);
try
FList.Add(AItem);
finally
TMonitor.Exit(FList);
end;
end;
TInterlocked (Atomic Operations)
{ Para operações simples em Integer/Int64 — sem lock explícito }
TInterlocked.Increment(FProcessedCount);
TInterlocked.Decrement(FPendingCount);
TInterlocked.Add(FTotalBytes, LBytesRead);
TInterlocked.Exchange(FOldValue, LNewValue);
TInterlocked.CompareExchange(FTarget, LNewVal, LExpectedVal);
TThreadList<T> (Thread-Safe List)
var
FSharedList: TThreadList<string>;
{ Thread A: adicionar }
LList := FSharedList.LockList;
try
LList.Add('item');
finally
FSharedList.UnlockList;
end;
{ Thread B: ler }
LList := FSharedList.LockList;
try
for LItem in LList do
ProcessItem(LItem);
finally
FSharedList.UnlockList;
end;
TMultiReadExclusiveWriteSynchronizer (MREWS)
type
TThreadSafeCache = class
private
FData: TDictionary<string, string>;
FLock: TMultiReadExclusiveWriteSynchronizer;
public
constructor Create;
destructor Destroy; override;
function TryGet(const AKey: string; out AValue: string): Boolean;
procedure Put(const AKey, AValue: string);
end;
function TThreadSafeCache.TryGet(const AKey: string; out AValue: string): Boolean;
begin
FLock.BeginRead; // Múltiplas threads podem ler simultaneamente
try
Result := FData.TryGetValue(AKey, AValue);
finally
FLock.EndRead;
end;
end;
procedure TThreadSafeCache.Put(const AKey, AValue: string);
begin
FLock.BeginWrite; // Apenas uma thread pode escrever por vez
try
FData.AddOrSetValue(AKey, AValue);
finally
FLock.EndWrite;
end;
end;
Producer-Consumer Pattern
type
/// <summary>
/// Producer-Consumer com TT
Truncated for display — read the full file on GitHub.
Related Skills
ai-job-search
44.1kThe job search that runs on your machine. AI job application framework built on Claude Code: evaluate postings, tailor CVs, write cover letters, prep interviews. Fork it and own it.
claude-howto
41.7kA visual, example-driven guide to Claude Code — from basic concepts to advanced agents, with copy-paste templates that bring immediate value.
algorithmic-art
177.9kCreating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems.
interview-me
98.8kExtracts what the user actually wants instead of what they think they should want. Achieves this through one-question-at-a-time interview until ~95% confidence about the underlying intent
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
