Solved

Delphi when application closes its still being run in memory

Posted on 2007-04-11
8
622 Views
Last Modified: 2013-11-23
Hi,

I have been trying to upgrade a delphi 5 project to BDS2006 (This is the first time i have ever even seen delphi so i am < novice :-) ) and through peoples help on here have been reasonably successful.  The program interacts with a PCI card that measures speed.  I now i feel have the last bit to get working and it is done.

The problem i now have is that the application starts up and works correctly, but when i exit the application it exits from the application part in task manager, but keeps working in memory as can be seen in the processes part in taks manager.

There is a secondary thread created and i have manged to work out that it falls over at the same line each time.

The thread file i will put at the bottom of this post.  Basically in the destructor bit it gets to FTimerThread.Free; but does not get any further.  Also, i had a problem on startup after the thread created, it kept getting stuck in various parts after the thread was created.  I got around this by using the sleep(500); command a couple of times and think it had to do with the hardware being newer and hence quicker.  I have tried adding another sleep before the part but it does not work.

I only have brought up the startup problem because when either a break point was used or the code stepped through then the application would always start.  This is also the case on exit if i use a breakpoint prior to the bit where it stops working or step through the code it closes correctly.

Any ideas ???

unit ThdTimer;

interface
{****************************************************************************************}
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
{****************************************************************************************}
type
  TThreadedTimer = class;
{****************************************************************************************}
  TTimerThread = class(TThread)
    OwnerTimer : TThreadedTimer;
    Interval   : DWord;
    procedure  Execute; override;
    procedure  DoTimer;
  end;
{****************************************************************************************}
  TThreadedTimer = class(TComponent)
  private
    FEnabled        : Boolean;
    FInterval       : Word;
    FOnTimer        : TNotifyEvent;
    FTimerThread    : TTimerThread;
    FThreadPriority : TThreadPriority;
  protected
    procedure UpdateTimer;
    procedure SetEnabled(Value: Boolean);
    procedure SetInterval(Value: Word);
    procedure SetOnTimer(Value: TNotifyEvent);
    procedure SetThreadPriority(Value: TThreadPriority);
    procedure Timer; dynamic;
  public
    constructor Create(AOwner: TComponent); override;
    destructor  Destroy; override;
    procedure   Reset;
  published
    property Enabled: Boolean read FEnabled write SetEnabled default True;
    property Interval: Word read FInterval write SetInterval default 1000;
    property OnTimer: TNotifyEvent read FOnTimer write SetOnTimer;
    property ThreadPriority: TThreadPriority read FThreadPriority write SetThreadPriority;
  end;
{****************************************************************************************}
procedure Register;

implementation
{----------------------------------------------------------------------------------------}
procedure TTimerThread.Execute;
begin
   repeat
      SleepEx(Interval, False);
      Synchronize(DoTimer);
   until Terminated;
end;
{----------------------------------------------------------------------------------------}
procedure TTimerThread.DoTimer;
begin
   OwnerTimer.Timer;
end;
{----------------------------------------------------------------------------------------}
constructor TThreadedTimer.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  sleep(500);
  FEnabled                := True;
  FInterval               := 1000;
  FThreadPriority         := tpNormal;
  FTimerThread            := TTimerThread.Create(False);
  FTimerThread.OwnerTimer := Self;
  sleep(500);
  FTimerThread.Interval   := FInterval;
  FTimerThread.Priority   := FThreadPriority;
end;
{----------------------------------------------------------------------------------------}
destructor TThreadedTimer.Destroy;
begin
  FEnabled := False;
  UpdateTimer;
  FTimerThread.Free;
  inherited Destroy;
end;
{----------------------------------------------------------------------------------------}
procedure TThreadedTimer.UpdateTimer;
begin
  if FTimerThread.Suspended = False then FTimerThread.Suspend;
  if (FInterval <> 0) and FEnabled and Assigned(FOnTimer) then FTimerThread.Resume;
end;
{----------------------------------------------------------------------------------------}
procedure TThreadedTimer.SetEnabled(Value: Boolean);
begin
  if Value <> FEnabled then
  begin
    FEnabled := Value;
    UpdateTimer;
  end;
end;
{----------------------------------------------------------------------------------------}
procedure TThreadedTimer.SetInterval(Value: Word);
begin
  if Value <> FInterval then
  begin
    FInterval := Value;
    FTimerThread.Interval := FInterval;
    UpdateTimer;
  end;
end;
{----------------------------------------------------------------------------------------}
procedure TThreadedTimer.SetOnTimer(Value: TNotifyEvent);
begin
  FOnTimer := Value;
  UpdateTimer;
end;
{----------------------------------------------------------------------------------------}
procedure TThreadedTimer.SetThreadPriority(Value: TThreadPriority);
begin
  if Value <> FThreadPriority then
  begin
    FThreadPriority := Value;
    FTimerThread.Priority := Value;
    UpdateTimer;
  end;
end;
{----------------------------------------------------------------------------------------}
procedure TThreadedTimer.Timer;
begin
  if Assigned(FOnTimer) then FOnTimer(Self);
end;
{----------------------------------------------------------------------------------------}
procedure TThreadedTimer.Reset;
begin
  FTimerThread.Free;
  FTimerThread            := TTimerThread.Create(False);
  FTimerThread.OwnerTimer := Self;
  FTimerThread.Priority   := FThreadPriority;
  UpdateTimer;
end;
{----------------------------------------------------------------------------------------}
procedure Register;
begin
   RegisterComponents('Servocon', [TThreadedTimer]);
end;
{----------------------------------------------------------------------------------------}
end.

 earlier when creating the thread but managed to fix the problem by putting in a couple of

0
Comment
Question by:yo_daz_uk
  • 5
  • 3
8 Comments
 
LVL 21

Expert Comment

by:ziolko
ID: 18891887
once I've had problem with thread thats what i came up with:

that's how i create thread:
  FWMIThread := TWMIThread.Create(False);
  FWMIThread.FreeOnTerminate := False;

that's release:
  FWMIThread.Terminate;
  FWMIThread.WaitFor;  
  FreeAndNil(FWMIThread);

thread's main loop:
  while (not Terminated) do begin
    // some processing
    Sleep(1);
  end;


and second thing if you create component
check for component state in construcotr,
there's no reason for creating thread in design time (when you drop component
on form while designing app)
something like this:
constructor TThreadedTimer.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FEnabled                := True;
  FInterval               := 1000;
  FThreadPriority         := tpNormal;
  if not (csDesigning in ComponentState) then begin
    FTimerThread            := TTimerThread.Create(True);
    FTimerThread.OwnerTimer := Self;
    FTimerThread.Interval   := FInterval;
    FTimerThread.Priority   := FThreadPriority;
    FTimerThread.Resume;
  end;
end;

notice that i've changed TTimerThread.Create(False); to
TTimerThread.Create(True);
when you create thread, execute is called almost immidietly
and first thing you do is SleepEx() so there's chance that
thread will be in wait state before you set other properties (interval, priority)
if you dont want to create suspended thread and then call resume
you can override constructor and pass interval and priority as params.

other issue: consider using TTimer instead putting thread into sleep

ziolko.
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18891896
btw.
 if FTimerThread.Suspended = False then FTimerThread.Suspend; ->
 if not FTimerThread.Suspended then FTimerThread.Suspend

ziolko.
0
 

Author Comment

by:yo_daz_uk
ID: 18932000
I believe i read maybe in the borland help that you should not use the terminate() for the thread and use free as this ensures successful memory release from the thread.

However, I have now managed to fix the problem, but what are your thoughts on this ....

i simply have commented out the thread.free part.  This obviously does not sound ideal, but the thread is always running when the application is running (which is what is needed), and when the application terminates the thread is released from memory anyway.  So the only point it will terminate at is when the application exits, which is exactly as it was doing before.

This works.
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18932285
>>I believe i read maybe in the borland help that you should not use the terminate() for the thread and use free as this ensures successful memory release from the thread<<
yup thats why i set FreeOnTerminate to False and then call .Terminate then .WaitFor and then FreeAndNil() so all memory is released, i have no reports about memory leaks:)

well not calling .Free when app shuts down is ok, but what if you call Reset method of TThreadedTimer?
since you call .Free in this method it's possible that it will hang just like it does now when you terminate app.
moreover what if TThreadedTimer component will be created in run-time and destroyed in run-time? if you dont call .Free on thread, memory will be wasted.

ziolko.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:yo_daz_uk
ID: 18932581
Are you saying that because the reset calls the thread.free ?  You have to bear with me because this is the first time I have ever even seen delphi code.
0
 
LVL 21

Accepted Solution

by:
ziolko earned 250 total points
ID: 18932695
i'm not saying that Reset causes this behaviour but if app hangs on thread free it's highly possible that it will also hang on reset

ziolko.
0
 

Author Comment

by:yo_daz_uk
ID: 18938139
I understand.  Anyway as of now i am happy with the comment solution, but i will try yours if it does not work.

Thanks for your help.
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18939685
as long as it works any solution is good:)
ziolko.
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Suggested Solutions

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now