Lazarus
Programming => General => Topic started by: fredycc on May 25, 2010, 03:48:18 pm
-
Hi again; I have some questions about Threads; my case is: I have a single application, The MainThread and a secondary Thread; The second thread calculate the time each second is like a clock; this have the Synchronize method to help me display the time into my MainForm(MainThread), No problem here, the time is displayed correctly; But sometimes the mainThread try to connect with a db server, sometimes this take 5 seconds; in that time the second thread appear is paused; and start calculated again after connect to database. :o
I discover that if you don't assign the event that show the time calculated for the second thread; the second thread never paused, and still calculated in that 5 seconds; Thanks :-\
The Second Thread that calculate the time:
type
{ TMyThread }
TShowStatusEvent = procedure(textTime: TTime; objStatus: boolean) of Object;
TMyThread = class(TThread)
private
vstsObj: boolean;
FOnShowStatus: TShowStatusEvent;
procedure ShowStatus;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: boolean);
property OnShowStatus: TShowStatusEvent read FOnShowStatus write FOnShowStatus;
Time : TTime;
end;
implementation
constructor TMyThread.Create(CreateSuspended : boolean);
begin
FreeOnTerminate := True;
inherited Create(CreateSuspended);
end;
procedure TMyThread.Execute;
begin
While (not Terminated) do begin
Time := Time + 1/86400; //(24 * 60 * 60);
Synchronize(@Showstatus);
Sleep(1000)
end;
end;
procedure TMyThread.ShowStatus;
begin
if Assigned(FOnShowStatus) then begin
FOnShowStatus(Time, vstsObj);
end;
end;
MainThread:
procedure TfrmMainDesk.FormShow(Sender: TObject);
begin
if MyTime = nil then begin
MyTime := TMyThread.Create(True);
MyTime.Time := Now - 30/1440;
MyTime.OnShowStatus := @ShowTime;
MyTime.Resume;
end;
end;
procedure TfrmMainDesk.ShowTime(textTime: TTime; objStatus: boolean);
begin
Label1.Caption := '[ '+ FormatDateTime('hh:mm:ssampm', textTime) + ' ]';
end;
-
I have some questions about Threads;
I can't find a question here.
-
My question will be; Why the second thread pause while the main thread try to connect with database?, Sorry
If I comment: MyTime.OnShowStatus := @ShowTime in the mainthread the second thread works fine. Of course never show the new time calculated.
-
I think I know what your asking.
why is your time off when it gets displayed?
the Synchronize places a request to be handed in the main codes Que (along with the keyboard, mouse, screen update and any timer or other event generators). until it gets serviced, it is paused.
what I had to do to get a time is to have the main thread go get the current value of the timer thread when it was ready for it. that way the sec thread keep on trucking while the OS has Main on hold. A timer in the main thread that gets the count form the timer thread and displays it is probably what your after.
constructor TTimeObj.Create(interval:integer; CreateSuspended: Boolean);
begin
Inherited Create(CreateSuspended);
FreeOnTerminate:=TRUE;
ticks :=0;
Mydelay := interval;
end;
procedure TTimeObj.Execute;
begin
while (not Terminated) do begin
sleep(Mydelay);
inc(ticks);
end;
end;
function TTimeObj.ShowTimer: UINT64; // to be called from mother
begin
if not assigned(Self) then exit; // safe code
result := ticks;
end;
-
Excuse me mas steindorff; I need create a timer to get the value of the second thread? and the timer is created in the mainform?; I don't know if it is possible, but to avoid use Synchronize Can I access the value calculated by the second thread since mainthread?, how? %)
Thanks.
-
the rest of the thread code not shown above:
Type
{ TTimeObj }
TTimeObj = class(TThread)
Mydelay:integer;
ticks :UINT64; // I can acess ticks form outside
// private
protected
procedure Execute; override;
public
function ShowTimer: UINT64;
Constructor Create(interval:integer;CreateSuspended:Boolean);
// destructor Destroy; override;
end;
here is the main code section:
some here I create the Thread with
mytimer := TTimeObj.Create(250,FALSE); // one tick every 250ms, start running
then when I'm ready to check the time
end_time :=myTimer.ticks; // div by 4 if you need seconds
If you need the screen to be updated at a req interval then drop a Ttimer on your form, set the interval to your update time and then add the code below into the OnTimer event. this way the thread keep on running even if the OnTimer event is delayed.
procedure TFMain.Timer1Timer(Sender: TObject);
var SecondSoFar :integer; // or float if sub seconds
begin
SecondSoFar := MyTimer.ticks div 4; //
// then convert ticks -> final output. for just plan seconds do..
Label1.Caption := '[ '+ Format('seconds =%d', [SecondSoFar] ) + ' ]'
end;
note:
Accessing the threads "Ticks" variable while it is being update may cause some misque somewhere but I've been using this code off and on for a few mouths without any exceptions fireing off at the 4 ticks/second rate.
-
Looks interesting mas steindorff I'll test it; :).
Thanks a lot. ;D
-
I do not completely understand what you need, but if your main thread is "blocked" for 5s connecting to the DB, then the GUI is blocked - period -
So generally it would be better to put your "blocking" code in a separate thread.
-
So generally it would be better to put your "blocking" code in a separate thread.
Hi, theo; thanks for ask, thats the reason for the second thread like you say; It's created when I show the Main form, and calculate the time each second (add one second)(I don't want to show the time of the machine); but the second threads is paused when I use synchronize to acces the GUI to display the new time; is like mas steindorff explain:
the Synchronize places a request to be handed in the main codes Que (along with the keyboard, mouse, screen update and any timer or other event generators). until it gets serviced, it is paused.
If I ommit synchronize in the second thread, the thread never is paused; but I can't access the GUI to display the time calculated.
I lost that 5 seconds, sometimes more in the calc each time connect to data base.
-
Thnaks a lot mas steindorff; the code you send me, work great; the Mainform sometimes "blocking" but the thread keep on running. ;D
-
glad I could help. Lazarus has a lot of potenal if we all keep working as a team