cannot terminate an externally created thread?
The VCL have a new Texternalthread class which derives from TThread
And can be attached to a existing Win32 thread object by filling in
The Handle and ThreadID properties using the GetCurrentThread () and GetCurrentThreadID ()
WIN32 API functions instead of creating a new thread object by calling the Win32 API CreateThread () function.
The error you is seeing can only occur
If you is calling Terminate () on a texternalthread instance.
This was correct, the exception is raised from a Terminate () call.
How shoud texternalthreads is terminated?
A regular TThread object that you create yourself are not a texternalthread instance.
The error message is seeing cannot is raised by your own custom threads,
Unless you has corrupted memory that causes the Tthread.fexternalthread member to become a Non-zero value.
The only thing in the VCL this creates Texternalthread instances is the Tthread.getcurrentthread () method.
You can ' t terminate a Texternalthread object, by design, because it represents a thread that Texternalthread does not own.
The *only*-on-the-Terminate () on a TThread object
Whose Externalthread property is true,
such as a TThread object that is obtained from the Tthread.getcurrentthread () method.
But another possibility would is if random memory got corrupted
And the Tthread.fexternalthread member was a unsuspecting victim of that corruption.
Is this possible, that XE4 creates texternalthread by default?
No.
The *only*-Texternalthread is created are if the Tthread.getcurrentthread () method is called.
What is Texternalthread? " Cannot terminate externally created thread "when terminating a thread-based timer
This happens half of the time when closing my application in
Which I has placed a tlmdhitimer on my form with design time, Enabled set to True.
In my Onformclose event, I call mylmdhitimer.enabled: = False.
When this was called, I sometimes (about half of the time) get this exception.
I debugged and stepped into the "call" and found that it's line 246 in Lmdtimer.pas that gives this error.
Fthread.terminate;
I am using the latest version of Lmdtools.
I did a complete reinstall of LMD tools before the weekend and
There are removed and re-added the component to the form properly as well.
From the What I ' ve found, this have something to does with Texternalthread,
But there's no documentation on the it from Embarcadero and
I Haven ' t found anything referencing it within the Lmdtools source code.
Using fully updated RAD Studio, Delphi 2010.
What really upsets me here's that there's no documentation whatsoever.
Google yeilds One result that actually talks about it which someone says that the error
is caused by trying to terminate a texternalthread.
But looking at the Source-code in the Lmdhitimer, not once does it aim to do anything but create a regular tthread.
The one Google result I could find,
Thread:cannot terminate an externally created thread?
On Embarcadero mentions using GetCurrentThread () and GetCurrentThreadID () to get the data necessary
To hooks on to a existing thread, but the tlmdhitimer does no such thing.
It just creates its own tthread descendant with its own Create () constructor
(Overridden of course, and calls inherited at the start of the constructor)
So ... What's the heck is this texternalthread?
Has anyone else run to this kind of exception?
And perhaps figured out a solution or workaround?
I ' ve asked almost the exact same question to Lmdtools ' own support,
But it can ' t hurt-to-ask in multiple places.
Thank advance for any assistance.
Texternalthread wraps a thread that the Delphi RTL didn ' t create.
It might represent a thread belonging to the OS thread pool,
Or maybe a thread created by the another DLL in the Your program.
Since the thread is executing code this doesn ' t belong to the associated Texternalthread class,
The Terminate method has no-to-notify the thread that is want it to stop.
A Delphi TThread Object would set its Terminated property to True,
And the Execute method that got overridden would is expected to check this property periodically,
But since this thread was Non-delphi code, there is no Execute method,
The Terminated property is only came to existence after the thread code is already
Written someplace else (not by overriding Execute).
The newsgroup thread suggests "s probably happening in your case:
to become a Non-zero value.
It might is due to a bug in the component library, or it could is due to a bug in your own code.
You can use the debugger's data breakpoints to try-to-find out.
Set a breakpoint in the timer ' s thread ' s constructor.
When your program pauses there, use the "Add Breakpoint" command
On the Run, menu to add a data breakpoint using the address of the new object ' s fexternalthread field.
Thereafter, if that field ' s value changes, the debugger would pause and show you what changed it is.
(The data breakpoint'll get reset each time you run the program
Because the IDE assumes the object won ' t get allocated at the same address each time.)
I did as you said, but the only time this breakpoint is triggered is
Upon the destruction of the component at the closing of the application.
I hit Shift+f7 to trace to the next step in the source code
(using debug Dcus, so I get to see all the underlying Delphi classes too)
And the call stack looks as follows:pastebin.org/88904
That's looks to me like it's just doing the regular destruction of form components.
The call stack, you show was not the destruction of the timer component.
It looks like it ' s the destruction of some form.
Was the Fexternalthread field still False?
What new value does that memory contain when the data breakpoint triggered?
Yes, it looks to be the destruction of my application ' s main form.
The Timer component is placed on it, which makes me interpret the call stack
As the component being destroyed during the form ' s destruction
(The form should destroy all components in it during destruction, right?)
It seems that when I evaluate the value of the address of Fexternalthread,
It always comes up as true and even when the Delphi debugger itself says that it is false.
I write down @FExternalThread and does Boolean ($Addess) in evaluation
And get ' true ' even during creation when just fexternalthread returns ' false '. –
Actually, no, nevermind.
I managed to propertly retrieve the value in the time the data breakpoint is triggered
Using Pboolean ($address) ^ and it is indeed set to true.
Edit:nope, happens on other computers too so it's supposedly something in this app I guess?
Still, it ' s weird that the data breakpoint only triggers during destruction and
The data is at that time already altered.
So my value has been changed without my application changing it?
I ' m gonna has to try running this app on another computer to see if the same error happens there too
Aaaaaaaaand I ran it on a different computer, no difference.
I just stepped through my code down to the very last line of my application ' s. dproj
and found the value at the address of Fexternalthread during the creation of the thread is false the entire time
Is there any chance the code might being trying to Terminate an already destroyed TThread?
This could easily happen if you have freeonterminate set.
I noticed your post while diagnosing a similar (opposite?) error,
"Cannot call Start on a running or suspended thread"
The constructor of a component placed on the main form.
When I removed the Start (), that error is replaced by more telling errors,
e.g. "Invalid pointer operation" and "Access violation",
In the corresponding destructor.
The component were trying to manipulate their TThread object after the TThread were freed,
Thus leaving things up to Murphy's law.
When I is fixed that, I is able to replace the start () call without the "Cannot call Start" error returning.
By analogy, could your problem is that address of your fexternalthread had been recycled
And clobbered before the destructor/terminate call?
In our case, we had a buggy implementation of the Singleton Instance Pattern;
But again, Freeonterminate also seems like a likely suspect.
[fyi:i ' m using I ' m using C + + under RAD Studio XE]
This same problem drove me nuts for several months.
I went over my thread code in detail until I nearly went blind.
Finally I bought a good exception system (Eurekalog) and
It drove me directly to a third party component this was causing the problem.
This component, tabled, have a property to set it-to-flash with some sort of timing thread.
Setting it to not flash solved the problem.
Problem is this FExternalThread
isn ' t initialized to false by default
When you ' re creating TThread
instance.
So can ' t guarantee what value is in this variable
(sometimes there can be true, sometimes false).
Yes, the FExternalThread
member is initialized if a TThread
object is created.
Being a TObject
descendant, all of the members is TThread
zero-initialized upon allocation
Before the constructor is and then TThread
called.
That means was FExternalThread
implicitally initialized to False.
The only-to- FExternalThread
can set to True is
If either an actual TExternalThread
object was created (such TThread.GetCurrentThread()
as by the class method),
Or if memory is being corrupted by the app ' s code.
Texternalthread TThread--Delphi--cannot terminate an externally created thread?