Texternalthread TThread--Delphi--cannot terminate an externally created thread?

Source: Internet
Author: User

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?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.