I'm studying these two examples from these questions
- Pausing-a-thread-with-a-property (Remy's Answer).
- Do I need TThreads? If so can I pause, resume and stop them? (LU RD Answer).
What techniques I was using to debug?
That got me to find a bug in the second answer. This was my comment:
The example you have shown has a bug: If you let the task finish it
will show task terminated on the label and not task done because you
btnCancelTaskClick(Self); after the label's caption is set
to task done which will destroy the thread which will wake up the
cancel event and breaks the loop resulting in posting the second
message which will change the caption to task terminated. the solution
would be to add this line
if not readyFlag then before the call of the
postmessage. I have suggested an edit I hope you do not mind
What techniques am I using now?
- First techniques.
- Put break points everywhere and press Ctrl + Alt + T to see the stat of each thread.
Now here were things start showing its ugly side. I come to understand that threads run in a non synchronized way (which runs first will remain a ???). and these are the results I got from the first answer.
Example to reproduce
Create a new VCL project and add two TButtons on the main form. The first button creates the thread an the second one frees it.
procedure TForm6.Button1Click(Sender: TObject);
procedure TForm6.Button2Click(Sender: TObject);
th := TMyThread.Create;
press Button2 then Button1 and see what you can get
Results (under debugger):
In the first run I got GetLastError = 6 = ERROR_INVALID_HANDLE.
strangely the result of the
TEvent.WaitForMultiple was not
wrAbandoned when the TEvent was destroyed in the Destructor from the main thread (the main thread is the one executing the destroy code).
In the second run I got nothing and the thread was terminated properly.
- In the third run the code stuck on the CheckPause method, because the
wrAbandoned and it kept looping inside until terminated was True.
When launching the second answer without the debugger nothing happened for 10 runs.
Conclusions: I admit debugging a multi-threaded application is a nightmare. The best way I can design a proper non deadlocking free of bugs class is also a nightmare.
Checking for terminate will be my mode from now.
The errors I get in the debugger are not present always when I launch the code out of it (no idea why? I checked if the exceptions are swallowed some where else but with no success).
Question How can I improve the debugging process in a Delphi multithreaded code? So I get more of these errors.