Re: [Lazarus] TTimer woes (newbie)
On 03/31/2014 01:51 PM, Flávio Etrusco wrote: ... I guess simply changing your loop to: +++ repeat Application.ProcessMessages; until not timer1.enabled; +++ should make it work. That loop will work, but the CPU usage will be 100% and the CPU will run warm and the battery life on a laptop will be bad. I'd normally add a Sleep(10) in the loop to avoid those problems. Best regards, Paul www.TurboControl.com -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] TTimer woes (newbie)
On 01/04/2014 09:44, Michael Schnell wrote: In fact Bob is not doing this (eating up CPU Cycles), but he uses wait(), which only hampers it's own project. Actually Bob's "wait" uses his own TTimer-based code, and is not well designed. As Flavio wrote, he would be best to replace all his waits with a Sleep, and remove his timer altogether. Howard -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] TTimer woes (newbie)
On 03/31/2014 07:51 PM, Flávio Etrusco wrote: TTimer in Windows (and the basic timer support in Windows ) is implemented using window messages and you're not allowing the app to process messages inside your loop. This necessity is not limited to Windows nor to TTimer. Any Object Pascal Event handler (hence most code done in "normal" projects) is driven by the Project's Event Queue (which in Windows in turn is driven by Windows messages). In fact using "Application.ProcessMessages" in a loop is a workaround that is necessary when you really need a long winding loop in one of the (main Thread-) - Events) calculating something. It is a lot better style to do short events, whenever possible (maybe doing the long winding stuff in a TThread). Infinite (polling) loops in fact are (close to) forbidden, as they eat up CPU cycles that can better be used for other activities in the project or in any other program running on that PC. In fact Bob is not doing this (eating up CPU Cycles), but he uses wait(), which only hampers it's own project. This also usually is (close to) forbidden in the main thread, as the GUI will stop working while the main thread waits. Thus he should either use a TTimer instead of waiting and continue the work to be done in a newly entered Timer Event, or execute the code that includes the wait() in a TThread. -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] TTimer woes (newbie)
On Mon, Mar 31, 2014 at 2:24 PM, Bob Axtell wrote: > mine (a morse-code blinker) just doesn't work: > > unit Unit1; > > {$mode objfpc}{$H+} > > interface > > uses > Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, > ExtCtrls; > > type > > { TForm1 } > > TForm1 = class(TForm) > Panel1: TPanel; > Timer1: TTimer; > procedure FormKeyPress(Sender: TObject; var Key: char); > procedure Timer1Timer(Sender: TObject); > private > { private declarations } > procedure morse; > procedure dash; > procedure dot; > procedure wait(x: longint); > { public declarations } > end; > > var > Form1: TForm1; > a,b,i: byte; > count,dat, > ms,ls,mchar: byte; > tick: integer; > col: integer = clblue; > mtbl: string[16] = >#$bf#$be#$bc#$b8#$b0#$a0#$a1#$a3#$a7#$af#$42#$81#$85#$61#$20#$84; > > implementation > > {$R *.lfm} > > { TForm1 } > > procedure TForm1.Timer1Timer(Sender: TObject); > begin > timer1.enabled:= false; > end; > > procedure TForm1.wait(x: longint); > begin > tick:= x; > while tick > 0 do > begin > timer1.enabled:= true; > repeat until not timer1.enabled; > dec(tick) > end; > end; > > procedure Tform1.dash; > begin > Panel1.color:= col; > wait(30); > Panel1.color:= clwhite; > wait(10); > end; > > procedure Tform1.dot; > begin > panel1.color:= col; > wait(10); > panel1.color:= clwhite; > wait(10); > end; > > procedure tform1.morse; > begin > mchar:= $33; > ms:= ord(mtbl[succ((mchar shr 4) and 15)]); > ls:= ord(mtbl[succ(mchar and 15)]); > count:= (ms shr 5) and 7; > dat:= ms and 31; > for i:= 1 to count do > begin > if ((dat and 1) > 0) then dash else dot; > wait(10); > dat:= dat shr 1; > end; > wait(50); > { ms done, ls begins} > count:= (ls shr 5) and 7; > dat:= ls and 31; > for i:= 1 to count do > begin > if ((dat and 1) > 0) then dash else dot; > wait(10); > end; > wait(100); > end; > > procedure TForm1.FormKeyPress(Sender: TObject; var Key: char); > begin >case key of >'r': begin > col:= clred; > wait(15); > end; >'g': begin > col:= clgreen; > wait(15); > end; >'b': begin > col:= clblue; > wait(15); > end; >' ': morse; > end; > > end; > > end. > > any ideas? using v1.0.14 under WinXP. > > --Bob A > > TTimer in Windows (and the basic timer support in Windows ) is implemented using window messages and you're not allowing the app to process messages inside your loop. I guess simply changing your loop to: +++ repeat Application.ProcessMessages; until not timer1.enabled; +++ should make it work. If it's no problem that your app freezes the UI during the wait (like it does right now) you could just use Sleep() and abandon TTimer. OTOH the usual way to use TTimer is to do processing in the OnTimer handler, but then you'd have to change your code to store some state. Regards, Flávio -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] TTimer woes (newbie)
mine (a morse-code blinker) just doesn't work: unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls; type { TForm1 } TForm1 = class(TForm) Panel1: TPanel; Timer1: TTimer; procedure FormKeyPress(Sender: TObject; var Key: char); procedure Timer1Timer(Sender: TObject); private { private declarations } procedure morse; procedure dash; procedure dot; procedure wait(x: longint); { public declarations } end; var Form1: TForm1; a,b,i: byte; count,dat, ms,ls,mchar: byte; tick: integer; col: integer = clblue; mtbl: string[16] = #$bf#$be#$bc#$b8#$b0#$a0#$a1#$a3#$a7#$af#$42#$81#$85#$61#$20#$84; implementation {$R *.lfm} { TForm1 } procedure TForm1.Timer1Timer(Sender: TObject); begin timer1.enabled:= false; end; procedure TForm1.wait(x: longint); begin tick:= x; while tick > 0 do begin timer1.enabled:= true; repeat until not timer1.enabled; dec(tick) end; end; procedure Tform1.dash; begin Panel1.color:= col; wait(30); Panel1.color:= clwhite; wait(10); end; procedure Tform1.dot; begin panel1.color:= col; wait(10); panel1.color:= clwhite; wait(10); end; procedure tform1.morse; begin mchar:= $33; ms:= ord(mtbl[succ((mchar shr 4) and 15)]); ls:= ord(mtbl[succ(mchar and 15)]); count:= (ms shr 5) and 7; dat:= ms and 31; for i:= 1 to count do begin if ((dat and 1) > 0) then dash else dot; wait(10); dat:= dat shr 1; end; wait(50); { ms done, ls begins} count:= (ls shr 5) and 7; dat:= ls and 31; for i:= 1 to count do begin if ((dat and 1) > 0) then dash else dot; wait(10); end; wait(100); end; procedure TForm1.FormKeyPress(Sender: TObject; var Key: char); begin case key of 'r': begin col:= clred; wait(15); end; 'g': begin col:= clgreen; wait(15); end; 'b': begin col:= clblue; wait(15); end; ' ': morse; end; end; end. any ideas? using v1.0.14 under WinXP. --Bob A On Mon, Mar 31, 2014 at 2:35 AM, Howard Page-Clark wrote: > On 31/03/2014 10:25, Michael Schnell wrote: > >> On 03/31/2014 01:44 AM, Bob Axtell wrote: >> >>> can someone show a newbie how to use the two system timers? >>> >> >> What do you mean by system timers ? >> > > I think he means the TTimer and TIdleTimer found on the System page of the > Component Palette. > If you drop one of each on the main form of a new project with a label and > a memo, and add this code, it should give you an idea of how to use them. > > -- code begin -- > > unit Unit1; > > {$mode objfpc}{$H+} > > interface > > uses > SysUtils, Forms, ExtCtrls, StdCtrls; > > type > > { TForm1 } > > TForm1 = class(TForm) > IdleTimer1: TIdleTimer; > LAverageSoFar: TLabel; > MNumbers: TMemo; > Timer1: TTimer; > procedure FormCreate(Sender: TObject); > procedure IdleTimer1Timer(Sender: TObject); > procedure Timer1Timer(Sender: TObject); > private > FNumber: integer; > FRunningTotal: integer; > FCount: integer; > end; > > var > Form1: TForm1; > > implementation > > {$R *.lfm} > > { TForm1 } > > procedure TForm1.FormCreate(Sender: TObject); > begin > Randomize; > MNumbers.Clear; > > Timer1.Interval:=500; > Timer1.OnTimer:=@Timer1Timer; > Timer1.Enabled:=True; > > IdleTimer1.Interval:=1000; > IdleTimer1.OnTimer:=@IdleTimer1Timer; > IdleTimer1.Enabled:=True; > end; > > procedure TForm1.IdleTimer1Timer(Sender: TObject); > begin > LAverageSoFar.Caption:= > Format('Average of random numbers so far is > %n',[FRunningTotal/FCount]); > end; > > procedure TForm1.Timer1Timer(Sender: TObject); > begin > FNumber:=Random(101); > MNumbers.Lines.Add(IntToStr(FNumber)); > Inc(FCount); > Inc(FRunningTotal, FNumber); > end; > > end. > > -- code end -- > > Howard > > > > -- > ___ > Lazarus mailing list > Lazarus@lists.lazarus.freepascal.org > http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus > -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] TTimer woes (newbie)
On 31/03/2014 10:25, Michael Schnell wrote: On 03/31/2014 01:44 AM, Bob Axtell wrote: can someone show a newbie how to use the two system timers? What do you mean by system timers ? I think he means the TTimer and TIdleTimer found on the System page of the Component Palette. If you drop one of each on the main form of a new project with a label and a memo, and add this code, it should give you an idea of how to use them. -- code begin -- unit Unit1; {$mode objfpc}{$H+} interface uses SysUtils, Forms, ExtCtrls, StdCtrls; type { TForm1 } TForm1 = class(TForm) IdleTimer1: TIdleTimer; LAverageSoFar: TLabel; MNumbers: TMemo; Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure IdleTimer1Timer(Sender: TObject); procedure Timer1Timer(Sender: TObject); private FNumber: integer; FRunningTotal: integer; FCount: integer; end; var Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.FormCreate(Sender: TObject); begin Randomize; MNumbers.Clear; Timer1.Interval:=500; Timer1.OnTimer:=@Timer1Timer; Timer1.Enabled:=True; IdleTimer1.Interval:=1000; IdleTimer1.OnTimer:=@IdleTimer1Timer; IdleTimer1.Enabled:=True; end; procedure TForm1.IdleTimer1Timer(Sender: TObject); begin LAverageSoFar.Caption:= Format('Average of random numbers so far is %n',[FRunningTotal/FCount]); end; procedure TForm1.Timer1Timer(Sender: TObject); begin FNumber:=Random(101); MNumbers.Lines.Add(IntToStr(FNumber)); Inc(FCount); Inc(FRunningTotal, FNumber); end; end. -- code end -- Howard -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Re: [Lazarus] TTimer woes (newbie)
On 03/31/2014 01:44 AM, Bob Axtell wrote: can someone show a newbie how to use the two system timers? What do you mean by system timers ? In a normal GUI based application you normally use TTimer for time-based actions. You easily can create as many TTimers as you like (as well "visually" using the Lazarus GUI designer) as "dynamically" by having your program do myTimerN := TTimer.Create(Self); ) -Michael -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
[Lazarus] TTimer woes (newbie)
can someone show a newbie how to use the two system timers? --Bob A -- ___ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus