B4J Question Whats wrong with this Wait For construction?

kostefar

Active Member
Licensed User
Longtime User
Dear All,

I´ve only used wait for with websockets, like wait for ws_connected, so this was always refering to an event known by a library.
Then I thought that perhaps I could use Wait for in other situations, such as when one module calls a httpjob download in another module, then downloads something and upon completion calls another sub (or sets a boolean value to true).
So I´d wait for the other sub to be called, and then continue the code.
I´ve made a simplified version of the above, but it does not work. Obviously, I want it to get where it shows the word "Completed" in the log.

What´s wrong?

B4X:
#Region Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 600
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Dim timer As Timer
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    'MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
    MainForm.Show
timer.Initialize("timer",1000)
timer.Enabled = True
wait for test
Log ("complete")
End Sub
Sub test
End Sub
Sub timer_tick
    test
End Sub
'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Also, in situations like these - with jobdone - I find the way I work with it very unstructered, since there´ll be values received in the sub which initiates the job that I want to work with afterwards. As far as I know the only way of handling this is either to give the job a funny name that contains the values, or set the variants that hold the values globally. But is there a more elegant way?
 
Last edited:

Roycefer

Well-Known Member
Licensed User
Longtime User
The specific problem with your code is that Wait For waits for messages in the message queue. It cannot inspect the call stack. When you call the Sub test inside timer_tick, you are placing test on the call stack, not sending it to the message queue. What you need to do is use CallSubDelayed(Me,"test") inside timer_tick and then Wait For will catch it.
 
Last edited:
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Do you want to give a code example of what you are talking about? Wait for works great with a subs scoping of variables and no funny job names should be necessary.
 
Upvote 0

kostefar

Active Member
Licensed User
Longtime User
Do you want to give a code example of what you are talking about? Wait for works great with a subs scoping of variables and no funny job names should be necessary.

Thanks OliverA, but I´m good with my findings for now.

A simple example of what worked for me

B4X:
wait for (Get_Balance) Complete (Balance As Double)
Log (Balance)

B4X:
Sub Get_Balance As ResumableSub
    wait for (SendtoCryptopia ("GetBalance","GetBalance",$"{"Currency":"BTC"}"$)) Complete (result As String)
Complete (result As String)
Return (result)
End Sub

And the SendtoCryptopia, also being a resumablesub has this at the end of it :

B4X:
Wait For (j) jobdone(j As HttpJob)
    If j.Success Then
        wait for (Process_Httpincoming(j.GetString, jobname,params)) Complete (answer As String)
        Return (answer)
    End If
    j.Release

Where Process_Httpincoming deals with the type of request to cryptopia based on jobname and sometimes will need to know the params if for instance you´d be sending a request for a ticker that does not output the symbol you requested it for.

Took a little time to get used to this way of working instead of always having a bunch of globals set up, in fact I always hated that because you´d have alot of values to reset sometimes when you do something new within the same session and when used to the above structures there´s much less hassle getting an overview of your code.

Thanks big time to you all!
 
Upvote 0

kostefar

Active Member
Licensed User
Longtime User
Just got a bit challenged here.. If I want to wait for a particular request response, which may not arrive till I´ve send a number of http requests (like sending an order, and pulling the information about whether it´s been executed using another request), I need to start a timer. How do I send the parameters to the timer and have it returning the result?

EDIT: I think I came up with a way to do this without a timer..


B4X:
Dim starttime As String = DateTime.now
    Dim matched As Boolean
    Do While matched = False
    wait for (Cryptopia.SendtoCryptopia("GetBuyOrders","GetTradeHistory",coin)) Complete (answer As String)
    matched = Match_Asks(answer, ordermap)
    If DateTime.Now - starttime >= 10000 Then Exit
    Loop

Then I´ll know if the orders were for instance only partially executed after 10 secs, or won´t need to wait if there´s a match for their execution.

Nevertheless, I´d still be happy to know if there are ways to use a timer in constructions like these with wait for.
 
Last edited:
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…