EThread
Delphi Programming Language
Severity: CriticalWhat Does This Error Mean?
EThread is raised when something goes wrong with a TThread object in Delphi. The most common cause is an unhandled exception inside a thread's Execute method — Delphi catches it and wraps it as EThread. Thread errors are marked critical because an unhandled exception in a thread can silently kill that thread or destabilize the whole application.
Affected Models
- All Delphi versions
- RAD Studio
- Multi-threaded VCL and FMX applications
Common Causes
- An unhandled exception inside TThread.Execute — if the thread does not catch it, Delphi wraps it in EThread
- Accessing VCL controls directly from a background thread instead of using Synchronize or Queue
- Calling FreeOnTerminate := True and then trying to access the thread object after it has freed itself
- Thread synchronisation errors — accessing shared data without a TCriticalSection or TMonitor causing a data race
- Trying to resume a thread that has already been started, or freeing a thread while it is still running
How to Fix It
-
Wrap the entire body of your TThread.Execute method in a try/except block. Log any exception rather than letting it propagate. An unhandled exception in Execute is the most common source of EThread.
Example: try ... your code ... except on E: Exception do LogError(E.Message); end;
-
Never access VCL controls (forms, labels, edits, grids) directly from a background thread. Use Synchronize() to run that code on the main thread instead.
Example: Synchronize(procedure begin Label1.Caption := 'Done'; end); — this queues the UI update to run safely on the main thread.
-
If you use FreeOnTerminate := True, treat the thread object as freed the moment Execute finishes. Do not store the thread reference and use it later — the object may no longer exist.
For threads you need to monitor or interact with after creation, set FreeOnTerminate := False and free them manually when you are done.
-
Protect shared data with a TCriticalSection. Any variable read or written by more than one thread must be protected. Create the section in the main thread, and call Enter/Leave around every access.
Use a try/finally block: CS.Enter; try ... access shared data ... finally CS.Leave; end;
-
Enable the 'Use debug DCUs' option and run in the debugger. When the thread error occurs, the debugger will stop at the exact line. Check the Thread list window to see all running threads and their current state.
Thread bugs are notoriously hard to reproduce. Running under the debugger with all exceptions enabled (Tools → Debugger Options → 'Stop on Delphi exceptions') catches them reliably.
When to Call a Professional
EThread problems require careful debugging because thread bugs are often timing-dependent. If your application crashes randomly or behaves differently on different machines, a thread synchronisation bug is the likely cause. For complex threading scenarios, an experienced Delphi developer can help.
Frequently Asked Questions
What is the difference between Synchronize and Queue in TThread?
Synchronize blocks the background thread until the main thread has run your code. This guarantees the code has finished before the thread continues. Queue posts the code to the main thread's message queue and returns immediately — the background thread does not wait. Use Synchronize when the thread needs the result before it can continue. Use Queue when you just want to update the UI without waiting.
Can I access a TDataset from a background thread?
Not without careful precautions. TDataset and most database components are not thread-safe. The safest approach is to create a completely separate database connection for each thread — do not share a single connection between threads. Alternatively, do all database work on the main thread using Synchronize, though this reduces the benefit of threading.
My application crashes randomly but I never see EThread in the debugger. Could it still be a thread issue?
Yes. Many thread bugs cause access violations, memory corruption, or silent hangs rather than explicit EThread exceptions. Random crashes that are hard to reproduce consistently are a strong indicator of thread synchronisation bugs. Enable all exception notifications in the debugger and use tools like madExcept or EurekaLog to capture the full thread state at the time of the crash.