B4J Question Run function at set time

aaronk

Well-Known Member
Licensed User
Longtime User
Hi,

I am trying to work out the best way in running a function at a specific time that passes a string value to a function.

I am using a non-GUI app and I want to make it so that if I stop the B4J app and then start it again make it resume where it left off and not lose any delayed functions.

I was thinking of doing something like the following, but if I stop the B4J app and start it again it won't continue off where it was at and it would start from the beginning again.

I could set the sleep for 3 hours before it triggers the rest of the code, but if I stop the B4J app after 2 hours and then start it again, I don't want to wait 3 hours for the code to trigger and it should have to wait 1 hour since that is all that was left.

B4X:
RunMeTimeDelay(15000,"HelloWorld1") ' run function in 15 seconds
RunMeTimeDelay(5000,"HelloWorld2")    ' run function in 5 seconds
ActivateFunction("HelloWorld3")    ' Run it instantly

Sub RunMeTimeDelay(time As Int, value As String)
    Sleep(time)
    ActivateFunction(value)
End Sub

Sub ActivateFunction(value As String)
    Log(value)
End Sub

I was going to store the values in a SQL database so if I stop and start the B4J app it would remember the value, but it won't know how long it was running before it stopped.

As an example, think of it like an Uber. The user sets the time they want to be picked up and the pickup address in the B4A/B4i app. It sends the time and address to the B4J app. In the B4J app, the B4J app should trigger the function at the time the user entered and pass the address at that time. There could be over 1000-2000 users.

Any ideas on how I can run the function as specific time, even if I start/stop/start the B4J app ?
 

Chris2

Active Member
Licensed User
Longtime User
As an example, think of it like an Uber. The user sets the time they want to be picked up and the pickup address in the B4A/B4i app. It sends the time and address to the B4J app. In the B4J app, the B4J app should trigger the function at the time the user entered and pass the address at that time. There could be over 1000-2000 users.
There may well be better ways, but my first thought would be to store the actual time (ticks) with each pickup request in a map & database with an unique ID number as the key, then check each map entry on a timer...
(untested, incomplete code written on the fly...):
Sub Process_Globals
    Private mPickUps As Map
    Private lastPickupID As Int
    Private t As Timer
    Private sql As SQL
    Type PickUpInfo (address As String, PickUpTime As Long)
End Sub

Sub AppStart (Args() As String)
    mPickUps.Initialize
    sql.InitializeSQLite("databasePath", "databaseName", True)
    RetrieveStoredPickups
    StartMessageLoop
End Sub

Sub RetrieveStoredPickups
   
    Dim SenderFilter As Object = sql.ExecQueryAsync("SQL", "SELECT * FROM PickUpsTable", Null)
    Wait For (SenderFilter) SQL_QueryComplete (Success As Boolean, rs As ResultSet)
    If Success Then
        Do While rs.NextRow
            'populate mpickUps map with the results
'            mpickUps.Put(uid, CreatePickUpInfo(address, PickUpTme))
        Loop
        rs.Close
    Else
        Log(LastException)
    End If
   
    t.Initialize("t", 60000) 'interval depends on how accurately timed you want the function to be triggered
    t.Enabled=True
   
End Sub


Sub AddPickup (address As String, PickUpTme As Long) 'time of pickup in ticks
   
    mPickUps.Put(lastPickupID+1, CreatePickUpInfo(address, PickUpTme))
    sql.ExecNonQuery2("Insert into PickUpsTable (uid, time, address) VALUES (?,?,?)", Array As Object(lastPickupID+1, PickUpTme, address)) 'write this pickUp to the database also
    lastPickupID = lastPickupID+1
   
End Sub

Private Sub RemovePickup (uid As Int)
   
    mPickUps.Remove(uid)
    sql.ExecNonQuery2("DELETE FROM PickUpsTable WHERE uid=?", Array As Int(uid))
   
End Sub

Private Sub t_Tick
   
    For Each uid As Int In mPickUps
       
        Dim pInfo As PickUpInfo = mPickUps.Get(uid)
        If DateTime.Now > pInfo.PickUpTime Then     '> because we may have gone past the actual time
            ActivateFunction(pInfo.address)
            RemovePickup(uid)
        End If
       
    Next
   
End Sub

Sub ActivateFunction(address As String)
    Log(address)
End Sub


Public Sub CreatePickUpInfo (address As String, time As Long) As PickUpInfo
    Dim t1 As PickUpInfo
    t1.Initialize
    t1.address = address
    t1.PickUpTime = time
    Return t1
End Sub
 
Upvote 0

aaronk

Well-Known Member
Licensed User
Longtime User
There may well be better ways, but my first thought would be to store the actual time (ticks) with each pickup request in a map & database with an unique ID number as the key, then check each map entry on a timer...
That looks like a good idea on how I can do it.
 
Upvote 0
Top