Reputation: 33
I was trying to write a function that would take the amount of players currently logged into oldschool runescape and append the amount with the current time and date into a csv file. This function works great, but when I try to use the Timer function to repeat the function multiple times it shows an error. (I want it to run every 15 minutes on my idle laptop indefinitely).
This is the function:
function countplayers()
res = HTTP.get("https://oldschool.runescape.com")
body = String(res.body);
locatecount = findfirst("There are currently", body);
firstplayercount = body[locatecount[end]+2:locatecount[end]+8]
first = firstplayercount[1:findfirst(',',firstplayercount)-1]
if findfirst(',',firstplayercount) == 3
second = firstplayercount[findfirst(',',firstplayercount)+1:end-1]
else
second = firstplayercount[findfirst(',',firstplayercount)+1:end]
end
finalcount = string(first,second)
currentdate = Dates.now()
concatenated = [finalcount, currentdate]
f = open("test.csv","a")
write(f, finalcount,',')
write(f, string(currentdate), '\n')
close(f)
end
If I try Timer(countplayers(),10,10)
to test it out, I get this error:
**ERROR: MethodError: no method matching Timer(::Nothing, ::Int64, ::Int64)**
The same error appears if the timer is placed below the function and if the timer command is used in the REPL. What am I doing wrong? Thanks in advance!
Upvotes: 3
Views: 617
Reputation: 33259
The canonical way to do this is to start an async task and just run it in a loop and sleep in between:
@async while true
my_function()
sleep(15*60)
end
Because this block is async, evaluating this will return immediately and the task will just run in the background until the program exits.
Upvotes: 3
Reputation: 20248
In addition to other answers, here is another solution, more inline with what you were trying to do:
julia> using Dates
julia> function countplayers()
println("$(now()) There are 42 players")
end
countplayers (generic function with 1 method)
# Run `countplayers` every 3s, starting now (delay=0)
julia> t = Timer(_->countplayers(), 0, interval=3);
2020-11-10T17:52:42.904 There are 42 players
2020-11-10T17:52:45.896 There are 42 players
2020-11-10T17:52:48.899 There are 42 players
2020-11-10T17:52:51.902 There are 42 players
2020-11-10T17:52:54.905 There are 42 players
2020-11-10T17:52:57.908 There are 42 players
2020-11-10T17:53:00.909 There are 42 players
# When you want to stop the task
julia> close(t)
Upvotes: 4
Reputation: 42214
Extending on Stefan's suggestion how to start here is a full working and very useful code:
function dosomething(f, interval)
stopper = Ref(false)
task = @async while !stopper[]
f()
sleep(interval)
end
return task, stopper
end
Now let us see this action:
julia> task, stopper = dosomething(()->println("Hello World"),10)
Hello World
(Task (runnable) @0x000000001675c5d0, Base.RefValue{Bool}(false))
julia> Hello World
julia>
julia> stopper[]=true; # I do not want my background process anymore running
julia> task #after few seconds the status will be done
Task (done) @0x000000001675c5d0
Finally, it also should be noted that in production systems usually the most robust approach is to use system tools such as crontab
for controlling and managing such recurring events.
Upvotes: 4