4

I have seen that my Delphi app has more than one thread - 7 more exactly. OF COURSE I am not creating my own threads and I am only using 'classic' VCL controls. The program is idle. It just displays the main form. No dialogs are active, no personal/Indy/etc threads running.

  1. Wasn't supposed to have just one thread (the VCL main thread)?
  2. How do I know which of these (already running threads) is the main thread?

Note 1: This is related to Program freezes but the CPU utilization is zero
Note 2: I just realized that 2 or 3 of those threads are from the debugger (extra threads appear when I pause the program and invoke the 'CPU view' window).

Gabriel
  • 20,797
  • 27
  • 159
  • 293
  • Fordebugging purposes you can Name Threads. – nil Oct 21 '17 at 11:55
  • @nil - I know about named threads. BUT how can this help in my specific case? It can't. – Gabriel Oct 21 '17 at 11:56
  • 1
    Well point 2 asks that. Name it 'Main'. There is MainThreadID and CurrentThread to help identify. During Start of your program the CurrentThread should be the main I guess. – nil Oct 21 '17 at 12:00
  • @nil - My question was actually, "How do I know which thread is the main thread" in my specific case, when the program was already running. I wanted to debug that specific session, because I encountered a bug and I know that once I restart the program, the bug will not re-appear. But, well, I can use your advice and name the thread at app start up, to be prepared next time. Thanks! – Gabriel Oct 21 '17 at 12:06
  • Sometimes file dialogs create threads – David Heffernan Oct 21 '17 at 12:08
  • MainThreadID could help you nevertheless then. Use eveluate and compare the ID with the threads running. – nil Oct 21 '17 at 12:17
  • Using a `TThreadedQueue` creates two threads internally. – LU RD Oct 21 '17 at 12:20
  • 1
    Remove the parts of code/used compinents and units that don't affect the Q subject and finally give us an MCVE. Otherwise all our comments and answers will be nothing more then guesses. – asd-tm Oct 21 '17 at 18:23
  • We cannot ***simply guess*** what you're using that uses threads. It could be one of the Indy components, an ADO component, some other third party component or even piece of your own code that creates threads without you realising it. _However_: ***You can*** figure this out through a process of elimination. Remove parts of program: forms/units/components/chunks of code. Then retest and see if it still uses threads. – Disillusioned Oct 21 '17 at 21:50
  • Reduce the number of unaccounted threads to two, and I can tell you that wtsapi is responsible for them. – Sertac Akyuz Oct 22 '17 at 00:58
  • 1
    The VCL "hint" code also creates a thread. – Nat Oct 23 '17 at 03:01
  • @Nat - nice to know. – Gabriel Oct 23 '17 at 19:22
  • You can remark the WTSRegisterSessionNotification call in forms.pas to verify. – Sertac Akyuz Oct 23 '17 at 21:16

1 Answers1

5

As you see in the comments an answer to the first part of your question is broad. Just creating a new 'VCL Forms Application' project in Delphi XE7 and running it I had 4 Threads in the 'Thread Status' view. Others have mentioned TThreadedQueue, file dialogs, VCL hint code and more as a source for unaccounted threads.

For the second part of your question I suggested naming the main thread at startup with something like:

  TThread.NameThreadForDebugging('Main Thread', MainThreadID);

As you mention in the comments you might not be able to name it beforehand, so in an existing debug session you could do it ad hoc:

  • Invoke the Evaluate / Modify window

    • Ctrl+F7 or
    • Context Menu > Debug > Evaluate / Modify
  • Type in MainThreadID as expression to eveluate, resulting in the ID you are looking for.
  • If you want you can use the context menu entry 'Name Thread' in the Thread view to name the thread with that ID.

Thread Status with names

Identifying other threads with the IDE is possible, too. A double click on a thread in the Threads view will open the current call stack. Skimming over that you might already be able to tell if this is a native Delphi thread or an external.

For example one of the 'unidentified' - external - threads I did not create has following call stack:

enter image description here

While a Delphi thread I created for testing purposes has following, where the Delphi units are recognizable:

enter image description here

nil
  • 1,320
  • 1
  • 10
  • 21