TThread Facts

Delphi RTL TThread class has been an object of criticism since its introduction. Some criticism was deserved, some not. TThread implementation was gradually improving with every Delphi version. Here I am neither criticizing nor advocating the TThread class, just listing some details of TThread implementation in modern Delphi versions that Delphi programmer should know.

  1. TThread class does not allow setting a thread stack size – it is always equal to default value, usually 1 Mb. If you need a different value you can call BeginThread function directly, but that is a low level solution and not as handy as using TThread class;
  2. TThread constructor has the only parameter (CreateSuspended: Boolean). Irrespective of the parameter value the underlying Windows thread object is always created in suspended state:

        FCreateSuspended := CreateSuspended {...};
        FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), CREATE_SUSPENDED, FThreadID);
    

    A thread can start execution in AfterConstruction method (which is called after all inherited constructors):

      if not FCreateSuspended {...} then Resume;
    

    or later;

  3. Synchronization with the main thread does not work in console application. That means that you should not use Synchronize and Queue methods of TThreads class in console application. The same also applies to OnTerminate event which calls Synchronize method internally; you can override protected DoTerminate method instead;
  4. If you set FreeOnTerminate = True for a TThread instance, the instance is destroyed in the context of underlying background thread. Usually the destruction context does not matter, but in some cases it does. For example, create a TTimer instance in the constructor of TThread descendant, destroy timer in the destructor and see what happens (hint: an invisible window of TTimer instance is created in the main thread and destroyed in a different thread);
  5. TThread does not guarantee that Execute method will be called. I have bumped into this problem a little before.

Despite all issues we are better to use TThread class ‘as is’ in GUI applications. For my experiments I have written a simple alternative thread wrapper class that allows setting a thread stack size, always calls Execute method and does not contain synchronization methods; it is well suited for console applications.

Advertisements

5 thoughts on “TThread Facts

  1. The problem is not just in TThread, it is in the brains, or in the lack of brains in delphi developers. After having explained very carefully how TThread.Synchronize can be used, and misused, people continue to misuse and misunderstand it. After understanding the problems in TThread.Suspend/Resume, and its subsequent deprecation, some delphi developers fail to understand the following; That Threads are not simple, and that threading is almost never as easy and straightforward as you might like.

    TThread is not the one source for all your problem solutions related to multi-threaded programming, nor should it be. If you learn to use TCriticalSection properly, learn to use Events and wait for events, instead of using Sleep, and so on…. Perhaps you’ll do better. But whether one uses TThread or does not, is not the problem. The problem is whether or not you realize that multi-thread programming is not a class, it’s a learning process.

    W

  2. I posted QC #77203 to ask for a way to set the thread stack size when creating a thread.
    IMHO there’s also another flaw in TThread.WaitFor, because it doesn’t allow a time out (moreover Destroy calls it), if you call it and the thread is stuck the caller will be as well. See QC #9398 (I reported it in 2004… and the fix is simple, I believe)

  3. @WarrenP: I’d love to learn the ‘right’ way to use threading; can you point us to some resources please?
    TIA

  4. hi Serg, thanks for the summary. I have found you can in fact use Synchronize and OnTerminate in console applications as long as you remember to help them along a bit by calling CheckSynchronize() from the waiting loop. Anyway, console applications – I use them for unit testing but operationally they’re not much of a concern.
    @WarrenP, TThread and multithreaded programming _can_be_ simple and _does_ work well 99.9% of the time. I have been very productive with this class for almost 18 years of Delphi programming. It’s really a matter of being aware of the murky areas (“there be dragons”) and simply don’t go there.
    People wouldn’t use Synchronize if not for the well known VCL weakness w.r.t. multithreading. I have developed a set of thread safe queues and related TThread-based accessors which makes programming with TThreads behind the scenes a pure pleasure.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s