Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Updated - Can a Timer.delayedCall() be cancelled? — Gideros Forum

Updated - Can a Timer.delayedCall() be cancelled?

MellsMells Guru
edited August 2012 in General questions
Hi,

Update : How to cancel a Timer.delayedCall()?

I'm facing something strange.
I'm creating a few timers and I'm storing them in a table.
local playerName = "Miki"
timer = Timer.new(0, 1)
timer:start()
self.charaTimers[playerName] = timer
print (timer) -- table: 0x109df5d50
Later I try to retrieve my timers and stop them :
for i, j in pairs(self.charaTimers) do		
	print (j)  -- Displays table: 0x109df5d50 
        print (j:isRunning()) -- false	
        self.charaTimers[i]:stop()		
        -- or j:stop()
 
end
Timers keep on running. So I thought I'm mistaking with pointers but it seems that 0x109df5d50 confirms that I should be able to do j:stop()

I'm trying to know if there is anything that looks wrong here before searching somewhere else, but I'm 99% sure that those timers aren't modified anywhere else.

Do you have any ideas?
Thank you.


Dislikes: harlock74

twitter@TheWindApps Artful applications : The Wind Forest. #art #japan #apps
+1 -1 (+0 / -1 )Share on Facebook

Comments

  • Are you getting an error? From looking at your code, isRunning() is returning false because the timer will probably have already stopped because on creation there is no delay and it is only supposed to iterate once. If you wanted the timer to keep running and then be able to stop it when you want, I believe you would want to do something like Timer.new(0,0). Hope this helps, but maybe I'm misunderstanding what the problem is.
  • @zvardin Thank you for your help.
    I wanted to simplify my example script and I deleted a line. In fact I have :
    self.charaTimers[playerName].delayedCall(handicap, function()											      --do something here
    end)
    handicap is a value between 5 and 8 secs.
    So when I check if my timers are running after 3 secs only, isRunning() should display "true".
    My problem is that I can't access the timers that I stored in my table, and my goal is to stop (or pause) them.

    I want the timer to stop itself after one iteration, or it should be stopped by an external event if it's still running.
    twitter@TheWindApps Artful applications : The Wind Forest. #art #japan #apps
  • zvardinzvardin Member
    Accepted Answer
    Hmm... reading the documentation, I don't think using the delayedCall function matters if you call it on an instantiated timer and is more of a static function, so you can just do Timer.delayedCall(1000, someFunc).

    How are the Timers being instantiated? Because it still seems as if they wouldn't be running even with the line you are showing.
  • Your comment put me on the right path.
    I assumed (and I was wrong) that a timer is running (since it was already created) when a delayedCall is set, but it's not.

    I chose an alternative :
    self.charaTimers[playerName] = Timer.new(handicap, 1)
    self.charaTimers[playerName]:addEventListener(Event.TIMER, function ()  -- Do something here -- end)
    self.charaTimers[playerName]:start()
    My problem is solved but here is my last question (and I'll update my post title) :

    Can a delayedCall be cancelled?
    twitter@TheWindApps Artful applications : The Wind Forest. #art #japan #apps
  • Hm... I don't see anything that would allow you to... although is there any reason in that scenario not to just use a timer so you could stop it yourself? It seems like delayedCall is purely for a quick and easy way for a one-time delay.

    Interestingly, I tried a quick test and it seems to copy the function entirely because if I set a delayedCall on a function, but before the time is up remove the function or set the function to something else, the original function definition is still called.

    Likes: newbie2018

    +1 -1 (+1 / -0 )Share on Facebook
  • although is there any reason in that scenario not to just use a timer so you could stop it yourself?
    I was thinking that it's always better to avoid adding eventListeners on a high number of objects (imagine snow particles for ex.) and that Timer.delayedCall could be a solution if I could cancel in special cases.
    twitter@TheWindApps Artful applications : The Wind Forest. #art #japan #apps
  • Ah ok, I was assuming under the hood it was essentially doing the same thing just adding a convenient way to do something so simple.

    Maybe @atilim could confirm? ;) Otherwise might be able to try to do some stress tests to see if there seems to be any significance between the two.
  • It seems that an official solution to the problem has been brought by @atilim

    Now Timer.delayedCall returns a Timer object so that either you can ignore the returned value or stop it whenever you want:
      local timer = Timer.delayedCall(1000, func)
      -- 
      timer:stop()

    Likes: newbie2018

    twitter@TheWindApps Artful applications : The Wind Forest. #art #japan #apps
    +1 -1 (+1 / -0 )Share on Facebook
  • atilimatilim Maintainer
    edited August 2012 Accepted Answer
    There is no performance difference between two. Here is the complete implementation of Timer.delayedCall:
    local function delayedCallWrapper(timer)
    	timer.func()
    end
     
    local function delayedCallWrapperWithData(timer)
    	timer.func(timer.data)
    end
     
    function Timer.delayedCall(delay, func, ...)
    	local t = type(func)
    	if t ~= "function" then
    		error("bad argument #2 to 'delayedCall' (function expected, got "..t..")")
    	end
     
    	local timer = Timer.new(delay, 1)
    	timer.func = func
     
    	if (select('#', ...) >= 1) then
    		timer.data = select(1, ...)
    		timer:addEventListener(Event.TIMER, delayedCallWrapperWithData, timer)
    	else
    		timer:addEventListener(Event.TIMER, delayedCallWrapper, timer)
    	end
     
    	timer:start()
     
    	return timer -- only this line is added with the new version
    end
    I've just added the last line with the new version.
  • alexzhengalexzheng Guru
    edited August 2012
    Can you make it one step further to support mutiple arguments to func?
    Although we have talked about some unofficial implementation, it would be better if it is support in the sdk itself

    Likes: newbie2018

    +1 -1 (+1 / -0 )Share on Facebook
  • atilimatilim Maintainer
    edited August 2012
    I see. In this case, does this solution suit you?
    local function func(t)
        print(t[1], t[2], t[3], t[4])
    end
     
    Timer.delayedCall(1000, func, {10, 20, 30, 40})
    Maybe I should extend whole event system for multiple arguments.

    Likes: Mells, newbie2018

    +1 -1 (+2 / -0 )Share on Facebook
  • alexzhengalexzheng Guru
    edited August 2012
    yes, exactly.
    Mutiple arguments for event system is what I have expected since I begin using gideros :D

    Likes: atilim

    +1 -1 (+1 / -0 )Share on Facebook
  • Multiple arguments for event system would make my life easier, my code cleaner and my hair shiny, silky, soft and beautiful.

    Likes: newbie2018

    twitter@TheWindApps Artful applications : The Wind Forest. #art #japan #apps
    +1 -1 (+1 / -0 )Share on Facebook
Sign In or Register to comment.