B4J Question Events in a class and when using Callsub/Callsub delayed

Coldrestart

Member
Licensed User
Longtime User
Hello,

First of all my application is in B4J, so my starting point is a Main module.
Searching the forum, I read a lot about the Callsub methods, but it is still not clear when to use them, and when not to use them.
To understand it better, I have some questions:

-Question 1:
When you create an instance of a class in the Main module, is that class running in the same thread as the Main module?

-Question 2:
I have a public function in a Main module, that access a private variable in the Main module.
I have a class, that is created in the Main module. In the class is a timer configured.
On the event of that timer, the class is calling the public function that changes the private variable in the Main module.
The call is done without callsub, just a call of the function -> Main.ThePublicFunctionInMainModule
Is there a chance, due to an event in the Main module, and the event from the class, that there is a collision? (accessing the same variable from the class and the Main)
Or is this impossible?

-Question 3:
I suppose Callsub is an event that "synchronizes" with the thread/class where it is called? Is this correct?

Thanks in advance,

Kind regards,
Coldrestart.
 

LucaMs

Expert
Licensed User
Longtime User
1 - yes

2 - no, che calls will be queued (*)

3 - I didn't understand ?



(*).
In a class it is much more convenient to have a reference to the calling module/class and use it to run a routine of the latter.

I mean that instead of writing directly in the class source the name of the caller to execute a routine contained in it, as you are doing:
Main.ThePublicFunctionInMainModule
usually the caller is passed to the initialization of the class (and/or also to a property of the class, so that it can be changed at any time as needed):
B4X:
'Class MyClass
Sub Class_Globals
    Private mCallback As Object ' <--- will be the "caller"
    Private mEventName '  <--- this is the prefix, the initial part of the name of the event that will be called - not essential but very often very useful
' ...
End Sub


Public Sub Initialize(Callback As Object, EventName As String)
    mCallback = Callback ' <--- reference at class level of the data provided
    mEventName = EventName ' <--- reference at class level of the data provided
'...
End Sub

'Optional, you can allow the programmer to change the "caller", writing a property like:
Public Sub setCallback(CBack As Object)
    mCallback = CBack
End Sub
Public Sub getCallback As Object
    Return mCallback
End Sub


' When and where you need to run a "caller's routine":
'(1)
If SubExists(mCallBack, "ThePublicFunctionInCallbackModule") Then
    CallSub(mCallback, "ThePublicFunctionInCallbackModule")
End If

'or, more often:
'(2)
If SubExists(mCallBack, mEventName &  "_ThePublicFunctionInCallbackModule") Then
    CallSub(mCallback, mEventName &  "_ThePublicFunctionInCallbackModule")
End If

If you create an instance of the class in the Main module:
B4X:
Sub Process_Globals
   Private objInstanceOfMyClass As MyClass
'...
End Sub

Sub AppStart(...)
    objInstanceOfMyClass.Initialize(Me, "MyObj")
'...
End Sub

'(1)
Public Sub ThePublicFunctionInCallbackModule ' if called only from your class, you can declare it as Private, if objInstanceOfMyClass is created in this module.
' ...
End Sub


'(2)
Public Sub MyObj_ThePublicFunctionInCallbackModule ' if called only from your class, you can declare it as Private, if objInstanceOfMyClass is created in this module.
' ...
End Sub

This way your class does not necessarily have to be used in the Main, you can use it in other modules/classes and call the "ThePublicFunctionInCallbackModule" of the latter.
 
Last edited:
Upvote 0

Coldrestart

Member
Licensed User
Longtime User
Hello LucaMS,

Thanks for your explanation!
I understand that in object oriented programming, you should "hide" everthing that is in a class.
In my example I am violating these rules.

I think I made the mistake, I try to put a structure in my code, so the Main module don't get too big. (Losing overview or scroll in code too much)
I assume that is better to use a code module (Am I right??) in that case then creating a class, where you should work with get and set properties and the CallSub methods.

The problem that I have is that I need to pass a lot info from the GUI (All my objects on the GUI are in the Main module declared and accessed) to my class, then I need to create a lot of CallSub routines, so my code gets again less efficient.

In my Question 3, I don't understand very well, what a CallSub is doing exacly. Is it a "delegate" and "event" like in vb .net?
In the video of Erel, about the modules and classes, he also talks about the CallsubDelayed.
In the forum I found the following explanations:
-Callsub = calling a sub, where you can pass data and get the result in return. The program is waiting for the answer/the result in this case.
-Callsub delayed = calling a sub where you can pass data and get nothing back. The program continues and the call is done after that routine is finished.

2 - no, che calls will be queued (*)
So can I assume, that the Callsub delayed has nothing todo with multi threading, but only pushes the event in the queu, instead of doing that task immediatly?
Is gives another "priority" to that sub?

Thanks in advance,

And my apologies for my newbie questions.

Kind regards,
Coldrestart.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
I think I made the mistake, I try to put a structure in my code, so the Main module don't get too big. (Losing overview or scroll in code too much)
I assume that is better to use a code module (Am I right??) in that case then creating a class, where you should work with get and set properties and the CallSub methods.
Classes are usually written to be reused, as you know. Avoiding having a Main with thousands of lines of code seems like a good idea. Using code modules instead of classes... in B4J it is less important than in B4A, as even code modules can handle events, in B4J.

The problem that I have is that I need to pass a lot info from the GUI (All my objects on the GUI are in the Main module declared and accessed) to my class, then I need to create a lot of CallSub routines, so my code gets again less efficient.
Splitting the source into multiple classes, each with a specific task, and keeping them separate from the GUI is always a good rule.

Regarding the difference between CallSub and CallSubDelayed you have reported the explanation yourself: CallSub waits for the complete execution of the called routine, possibly returning values, if the Sub is a function; CallSubDelayed will run the execution of the routine only after the completion of the Sub in which the call is, not being able to receive return values.

In B4A it can also be used to bring up an Activity (the one that contains the routine to be called) but this is an old story, I would say obsolete, since it is now much more useful to use B4XPages.
 
Last edited:
Upvote 0
Top