Recent

Author Topic: TTimer elapsed do not runs asociated event... sometimes  (Read 13468 times)

torbente

  • Sr. Member
  • ****
  • Posts: 325
    • Noso Main Page
TTimer elapsed do not runs asociated event... sometimes
« on: September 17, 2014, 07:55:01 pm »
This is the most difficult thing i faced programming in +25K code lines app

Using Lazarus 1.2.4 on Windows 7 premium

Is a server-client app.

The server have a TTimer (Lets call it TimerCrazy), with an interval of 1000. Since i developed the server first, i added some buttons, only for debug, to simulate the server requests.

Example:

Code: [Select]
procedure TForm1.TimerCrazyOnTimer(Sender: TObject);
begin
stuff...
end;

procedure TForm1.BTPayClick(Sender: TObject);
begin
  ProcessComand('pay');
end;


There is a procedure called ProcessComand which do different things according to the command, sometimes turning on and sometimes turnin off the CrazyTimer

Everything works ok when i use this buttons, and the server sents  to the client the apropiate answers when i use the debug buttons.

Finally, y added to the client the ability to make the requests, so he client user can make the request whenever they want. The code is very simple.

ClientSayToServer := 'pay';

In the OnExecute procedure of the server, it just read the line and send it to processcomand(String);

Everytings works as expected but TimerCrazy, which never again runs TimerCrazyOnTimer, and im sure that is enabled (i added a new buttons to check its state and is enabled = true)

procedure TForm1.ButtonDebug(Sender: TObject);
begin
MemoDebug.lines.add('TimerCrazy State = '+booltostr(TimerCrazy.Enabled,true));
end;

Is enabled, but its on-timer procedure is not executed never again (i even try setting interval to 1 but it do not works neither)

Since im doing the same thing but from different sources i assume this "bug" is related to the sender of the ontime procedure. How i could fix this? Actually, what use have the sender parameter in a ontimer procedure? If i just delete it from the procedure, i get a sivsig error  %)

EDIT

I added this to he debug button to check if the TimerCrazy could "back to live" if it is called from a button

Code: [Select]
procedure TForm1.ButtonDebug(Sender: TObject);
begin
MemoDebug.lines.add('TimerCrazy State = '+booltostr(TimerCrazy.Enabled,true));
TimerCrazy.Enabled := true;
end;

But the TimerCrazy do not elapsed again neither.
 


« Last Edit: September 17, 2014, 08:13:10 pm by torbente »
Noso Cryptocurrency Main Developer
https://github.com/DevTeamNoso/NosoWallet

tr_escape

  • Sr. Member
  • ****
  • Posts: 432
  • sector name toys | respect to spectre
    • Github:
Re: TTimer elapsed do not runs asociated event... sometimes
« Reply #1 on: September 17, 2014, 08:18:19 pm »
hello torbente

it is too difficult to understand without codes or diagram of your project.

at first

- do you using state machine?
- how many clients have you got in this process?
- is your software has got threads? can you manage as well as your needs?

good luck



torbente

  • Sr. Member
  • ****
  • Posts: 325
    • Noso Main Page
Re: TTimer elapsed do not runs asociated event... sometimes
« Reply #2 on: September 17, 2014, 09:22:25 pm »
@tr_escape:

-State Machine? I dont know what it is, so probably not
-The server allows a maximum of 6 clients.
- Server-Client are multithread (Indy librarys) but i do not created more threads.

The problem (or bug) here is that the Timer aparently can not be enabled directly "from code"  since looks like it needs an Tobject to asocciate with. The servers do not hangs up, it is just like the TimerCrazy suddenly do not have an OnEvent procedure.
« Last Edit: September 17, 2014, 09:32:35 pm by torbente »
Noso Cryptocurrency Main Developer
https://github.com/DevTeamNoso/NosoWallet

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: TTimer elapsed do not runs asociated event... sometimes
« Reply #3 on: September 17, 2014, 09:46:06 pm »
Actually, what use have the sender parameter in a ontimer procedure? If i just delete it from the procedure, i get a sivsig error  %)

Sender is a reference to the timer instance itself. This is useful, for instance, if you have several timers in an application which share an OnTimer handler, and you need to be able to distinguish which timer is giving rise to that particular OnTimer event. Then you can un-enable that particular timer (say, if that is what is needed in your program logic at that moment).
Freeing Sender in an OnTimer event is simply committing software suicide (as you discovered), removing the timer altogether.
« Last Edit: September 17, 2014, 09:48:16 pm by howardpc »

torbente

  • Sr. Member
  • ****
  • Posts: 325
    • Noso Main Page
Re: TTimer elapsed do not runs asociated event... sometimes
« Reply #4 on: September 17, 2014, 09:50:24 pm »
Actually, what use have the sender parameter in a ontimer procedure? If i just delete it from the procedure, i get a sivsig error  %)

Sender is a reference to the timer instance itself. This is useful, for instance, if you have several timers in an application which share an OnTimer handler, and you need to be able to distinguish which timer is giving rise to that particular OnTimer event. Then you can un-enable that particular timer (say, if that is what is needed in your program logic at that moment).
Freeing Sender in an OnTimer event is simply committing software suicide (as you discovered), removing the timer altogether.

Yes, i know that there is the problem now. I added 1 more debug button to diabled the TimerCrazy and then re-enable it and it works.

How i can set a sender in this case to avoid this?

EDIT

I tried just running the procedure of the debug button. I Mind, following the example...

in the OnExecute section of the server

Comand := FromClient.ReadLn();
if command = 'pay' then BTPayClick(BTPay);

But it neither work!! WTF!! Im assigning the same sender now!! It is not the same than just clicking the button? OMFG!
« Last Edit: September 17, 2014, 10:04:03 pm by torbente »
Noso Cryptocurrency Main Developer
https://github.com/DevTeamNoso/NosoWallet

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: TTimer elapsed do not runs asociated event... sometimes
« Reply #5 on: September 17, 2014, 11:56:51 pm »
I can't follow you.
Sender is a value parameter, it is data that is passed to the OnTimer method, and although it is a variable it is constant in the sense that it denotes the identity of the timer that has just fired the event.
You can't "set a sender" - you can only read its value, and do something with that information (or ignore the information, as many methods with Sender parameters do when it is not relevant to the implementation of the event).

Never

  • Sr. Member
  • ****
  • Posts: 409
  • OS:Win7 64bit / Lazarus 1.4
Re: TTimer elapsed do not runs asociated event... sometimes
« Reply #6 on: September 18, 2014, 12:02:54 am »
i might be wrong but
for some reason i belive there is an error in a procedure of yours in another thread
your all app is hanging in the backround but your ui is responsive
« Last Edit: September 18, 2014, 12:49:53 am by Never »
Νέπε Λάζαρε λάγγεψων οξωκά ο φίλοσ'ς αραεύσε

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: TTimer elapsed do not runs asociated event... sometimes
« Reply #7 on: September 18, 2014, 12:12:55 am »
There are two conditions:
Code: [Select]
procedure TCustomTimer.Timer;
begin
...
  if (FEnabled) and (FInterval > 0) then
    DoOnTimer;
end;

Enable is true and Interval > 0.

Since you mentioned Windows, there is another possibility:
Quote
When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.

torbente

  • Sr. Member
  • ****
  • Posts: 325
    • Noso Main Page
Re: TTimer elapsed do not runs asociated event... sometimes
« Reply #8 on: September 18, 2014, 12:16:58 am »
@Never

Thats not the case. The entire app works perfect, actually, the form where i have the trouble continue working perfect and processing the client requests. But the TimerCrazy just stop and im unable to restart it from the client (but if i use the buttons in the server, the timer works perfect ok until an ew request is received from a client)

@howardpc

The server have buttons to do some tasks. If the client says to the server 'click this button', everything works as expected, but the timer just dont work anymore.

Im becoming crazy. A client request to click one button, the timer die. Then i click manually the same button, and the timer works perfect again.  :'(

@engkin

It sounds like chinese for me  :-\ 
« Last Edit: September 18, 2014, 12:22:03 am by torbente »
Noso Cryptocurrency Main Developer
https://github.com/DevTeamNoso/NosoWallet

Never

  • Sr. Member
  • ****
  • Posts: 409
  • OS:Win7 64bit / Lazarus 1.4
Re: TTimer elapsed do not runs asociated event... sometimes
« Reply #9 on: September 18, 2014, 12:25:20 am »
is your timer dynamicaly created? if so then you might have to free and reset it
Νέπε Λάζαρε λάγγεψων οξωκά ο φίλοσ'ς αραεύσε

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: TTimer elapsed do not runs asociated event... sometimes
« Reply #10 on: September 18, 2014, 12:34:28 am »
is your timer dynamicaly created? if so then you might have to free and reset it

you do know that a ttimer doesn't make your application asynchronous right?
That said, is it possible that the timer did not fire again because the previous job hasn't finished yet or when finished disabled or never re enabled the timer?

This is the digital world where everything has only two states on and off it either fires and fires correctly or it doesn't fire both cases are bugs in your code that need to be found, post simple small compilable sample that reproduces the error and we can grind on.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: TTimer elapsed do not runs asociated event... sometimes
« Reply #11 on: September 18, 2014, 12:35:54 am »
@engkin

It sounds like chinese for me  :-\ 
It does, doesn't it!. OK, how about some Pascal:
Get a global variable:
Code: [Select]
var
...
  tmrCk: integer = 0;  // I know, it is already zero.

Change your timer proc:
Code: [Select]
procedure TForm1.TimerCrazyOnTimer(Sender: TObject);
begin
  inc(tmrCk);
  MemoDebug.lines.add(Format('begin - %d',[tmrCk]));
stuff...  //<---- You might want to cancel this part temporarily
  MemoDebug.lines.add(Format('end - %d',[tmrCk]));
end;

torbente

  • Sr. Member
  • ****
  • Posts: 325
    • Noso Main Page
Re: TTimer elapsed do not runs asociated event... sometimes
« Reply #12 on: September 18, 2014, 07:59:09 am »
@Never: The timer was created using the IDE, and is never free in the whole code.

@taazz: Please, define asynchronous ? Yes, i know that all are zeros and ones (im an indi game designer since the years space quest was great) Plese, read the example again. Im just trying to fire a button in the server app when the client request it, and it do not works in the same way than if i click it directly. The Timer is enabled without doubt and the app is not hang. If i add a debug button with this:

TimerCrazy.enabled := true;

And click it, nothing happens when i click it. But if the buttons do this...

TimerCrazy.enabled := false;
TimerCrazy.enabled := true;

IT WORKS!!

I will try to code a little example to copy this issue and post it here.

@engkin: I added a line to check in the OnTimer procedure

MemoDebug.lines.add('TimerCrazy Elapsed');

But it neither works. The OnTimer event is not fired after the button was clicked via code.
Noso Cryptocurrency Main Developer
https://github.com/DevTeamNoso/NosoWallet

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1260
Re: TTimer elapsed do not runs asociated event... sometimes
« Reply #13 on: September 18, 2014, 12:41:46 pm »
TimerCrazy.enabled := false;
TimerCrazy.enabled := true;

IT WORKS!!

It honestly sounds to me like you have the timer configured in what I call one shot mode.  Some code inside your OnTimer is setting TimerCrazy.Enabled back to false again.  That code could be in a routine called from your OnTimer.

I'd breakpoint every single instance of your code that sets CrazyTimer.Enabled to False.  Disable all of them except for the one above (Lazarus - View - Debug Windows - Breakpoints - Right click - disable all, find the one you actually want, right click - choose enable).  Run.  When you hit the breakpoint above re-enable all the breakpoints and run.   My money is on an unexpected .enabled := False being stopped at next.

(And if you're doing any TTimer(Sender).Enabled stuff, breakpoint those too)
Lazarus Trunk/FPC Trunk on Windows [7, 10]
  Have you tried searching this forum or the wiki?:   http://wiki.lazarus.freepascal.org/Alternative_Main_Page
  BOOKS! (Free and otherwise): http://wiki.lazarus.freepascal.org/Pascal_and_Lazarus_Books_and_Magazines

torbente

  • Sr. Member
  • ****
  • Posts: 325
    • Noso Main Page
Re: TTimer elapsed do not runs asociated event... sometimes
« Reply #14 on: September 18, 2014, 01:23:06 pm »
In anycase, why TimerCrazy works as expected when the button is clicked manually? Im pretty sure this is caused for some bug in the TTimer thread. Something related to the sender.

I already did the steps to find the "wrong" timer.enabled:= false; There are just one and it is not called after the timer is enabled. SURE! Also remember that my first step to know what was happening was this

MemoDebug.lines.add('TimerCrazy State = '+booltostr(TimerCrazy.Enabled,true));

Always true!

Actually, due to the logic of the app, the Timer is really disabled when the button is clicked, and the button click routines should enabled it; it works perfect with the button pressed normally, but not when there are not user input.

« Last Edit: September 18, 2014, 01:27:00 pm by torbente »
Noso Cryptocurrency Main Developer
https://github.com/DevTeamNoso/NosoWallet

 

TinyPortal © 2005-2018