Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 6 of 6 total
Thread OT: Revisiting Threads - Memory Leak
Tue, Feb 26 2013 1:44 AMPermanent Link

Adam H.

Not DBISam related (except for the fact that the thread actually does
create sessions, etc Smile)

I've spent a number of hours trying to track this down with no success -
and I was wondering if someone may be able to assist please.

I've created a little thread unit (in binary dbisam newsgroup under
'[Threadunit] - Memory Leak').

This thread unit appears to run fine for me except one issue - which is
a memory leak.

It doesn't seem to use up more memory in this app (although I still get
a reported memory leak), but the parent app which runs threads exactly
the same does use up memory.

I'm wondering if I've done something basically wrong, of if anyone would
care to take a peak?  Smile

Eternally grateful...

Adam.
Tue, Feb 26 2013 4:04 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Adam


If you set FreeOnTerminate to True things work well.

Reading between the lines, since its for emails I suspect you need a queue mechanism and just leave the thread servicing the queue and olny shut it down when the app closes.

Depending on what components you're using I may / may not be able to help.

Roy Lambert [Team Elevate]
Tue, Feb 26 2013 8:45 AMPermanent Link

Raul

Team Elevate Team Elevate

Adam,

On 2/26/2013 4:04 AM, Roy Lambert wrote:
>
> If you set FreeOnTerminate to True things work well.
>

I agree with Roy - you either need to set FreeOnTerminate  or explicitly
destroy the thread.

Doing "emailthread := nil;" is not same as freeing : you need to do
EmailThread.Free actually though to do it properly you need some kind of
notification mechanism.

Setting emailthread:=nil inside Execute is not really a good practice.

Note also that OnTerminate is executed in the context of main thread so
i generally don't recommend "EmailThread.OnTerminate :=
EmailThread.onfinish" since you're running this on main thread so
"EmailThread.OnTerminate := TForm1.ThreadOnfinish;" is the way to do it.

Calling Terminate inside your Execute is not really needed - your thread
will exit at the end of Execute anyways so Terminate is usually called
from main thread.

Raul
Tue, Feb 26 2013 4:38 PMPermanent Link

Adam H.

Hi Raul and Roy,

Thanks for your replies.

> Doing "emailthread := nil;" is not same as freeing : you need to do
> EmailThread.Free actually though to do it properly you need some kind of
> notification mechanism.
>
> Setting emailthread:=nil inside Execute is not really a good practice.
>
> Note also that OnTerminate is executed in the context of main thread so
> i generally don't recommend "EmailThread.OnTerminate :=
> EmailThread.onfinish" since you're running this on main thread so
> "EmailThread.OnTerminate := TForm1.ThreadOnfinish;" is the way to do it.

Aaah - so effectively what I should be doing is doing the freeing (if I
want to call it explicitly) and nil'ing on the Mainform.OnFinish
property - as it runs outside of the thread, after it's completed.

Beautiful - really appreciate the help. I believe I'm slowly getting the
hang of (and becoming more comfortable) with threads. Smile

Thank you!

Adam
Wed, Feb 27 2013 3:43 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Adam


Since you're new to threads I'll give you the Roy Lambert quick appreciation course <vbg>

1. Develop all of the thread code initially as a separate foreground application - this makes debugging MUCH easier
2. Whilst doing this observe the rules of isolation - make sure that you unit (NOT form) contains everything that it needs to operate and that it doesn't reference anything outside of itself.
3. Add in any necessary, and only those necessary, external links. Make sure they are all protected by accessing only within a critical section
4. Where possible, if the thread needs start up parameters, pass them into the threads creator as parameters and transfer to local variables within the constructor (this pretty much guarantees isolation)
5. If you need to pass messages / progress back to the main form use PostMessage do not use a main form variable even if wrapped in a critical section since this will "stall" the thread
6. If the thread is doing the same thing over and over again just with different data (eg sending emails) look at creating a queue. Create the thread at the beginning of the app, terminate at the end and check the queue at intervals (within a critical section obviously). With DBISAM or ElevateDB you have a ready made queuing mechanism and you'll already have isolation in place so its easy.


I've given you a couple of examples. AlarmChecks is a more recent bit of code so probably represents better practice as I see it. frmQueue is from TMaN (my mail and news reader). Its a good many years old, not as well written but it may give you some ideas.

Roy Lambert [Team Elevate]







Attachments: AlarmChecks.pas frmQueue.dfm frmQueue.pas
Mon, Mar 11 2013 5:50 PMPermanent Link

Adam H.

Thanks Roy,

I'm just returning from a week away from work, so I've got a bit on my
plate, but I'll check this out as soon as I can! Really appreciate the
time you take to help me out. If you're ever down under look me up - I
owe you! Smile

Cheers

Adam.
Image