iOS Question Loop blocking Main thread callsubdelayed

joop

Active Member
Licensed User
Longtime User
Hi , I have a long loop to read and write a matrix, this works fine
with android with DoEvents in the code to do events
like handeling button clicks.

With IOS the main thread is blocked , I read on this form that
you can split the loop into some parts so the main thread
will not be blocked,you can do this with Callsubdelayed.
Each Callsubdelayed will be executed when the previous is
finished.

So I tried this but it does 'nt work.

Here is my source:

B4X:
Sub Button1_Click
loop1
End Sub

Sub Button2_Click
Button2.Text = "Pressed!"  
End Sub


Sub loop1
Button2.text = "loop1"
Dim size As Int = 800000
Dim value As Int
For j= 0 To size
        value = testarray1(j)
        testarray2(j) =value
     Next
     If DateTime.Now > lastPreviewSaved + 100 Then 'shouldn't block main tread ?
      lastPreviewSaved = DateTime.Now               ' so change button2.txt ?
     End If  
CallSubDelayed(Me,"loop2")       
End Sub


Sub loop2
Button2.text = "loop2"
Dim size As Int = 800000
Dim value As Int
For j= 0 To size
        value = testarray1(j)
        testarray2(j) =value
     Next
     If DateTime.Now > lastPreviewSaved + 100 Then
      lastPreviewSaved = DateTime.Now   
     End If  
CallSubDelayed(Me,"loop3")            
End Sub

Sub loop3
Button2.text = "loop3"
Dim size As Int = 800000
Dim value As Int
For j= 0 To size
        value = testarray1(j)
        testarray2(j) =value
     Next
     If DateTime.Now > lastPreviewSaved + 100 Then
      lastPreviewSaved = DateTime.Now   
     End If  
CallSubDelayed(Me,"loop4")            
End Sub

Sub loop4
Button2.text = "loop4"
Dim size As Int = 800000
Dim value As Int
For j= 0 To size
        value = testarray1(j)
        testarray2(j) =value
     Next
     If DateTime.Now > lastPreviewSaved + 100 Then
      lastPreviewSaved = DateTime.Now   
     End If      
End Sub

Output is :
loop1
loop2
loop3
loop4

This is ok , but when button2 is pressed the reaction is after all the loops
are finished , So the complete loop stil blocks all the button events.
Buttons have a very low priority in (IOS or B4i ?) can I change this ?,so it will
not be blocked by a simple Loop.

Maybe I use Callsubdelayed wrong, has anyone tried this before ?
 

joop

Active Member
Licensed User
Longtime User
Yes ,I know that is what I am trying to do .
This part
B4X:
If DateTime.Now > lastPreviewSaved + 100 Then
      lastPreviewSaved = DateTime.Now  
     End If
should not block the main thread ,and should pick up the
button event , but it doesn't work .
 
Upvote 0

joop

Active Member
Licensed User
Longtime User
I am reading and writing a large array in a for next loop
can be up to 1000000

for i = 0 to 1000000
read and write an array
next

of course this will block and there is no reaction on my buttons.
Apple will never approve this.

In Android I dit something like this:
if i modulo 20000 = 0 then DoEvents in the array read and write loop .

But I dont know how to do this in IOS
 
Upvote 0

joop

Active Member
Licensed User
Longtime User
It is also to slow in release mode.

this is the loop: it is called about 6 times.

B4X:
Dim array1 (1000000) As Byte
Dim array2 (1000000) As Byte

size = array1.length -1

For i= 1 To size   
        value = array1(i)
        If value < 6 Then value = 0    
        If array2(i) + value  < 75 Then
           array2(i) = array2(i) + value
        Else
          array2(i)=75 
        End If
        If i mod 200000 = 0 Then
          'handle main tread event buffer
        End If
      Next


So what your meaning is , it's not possible to give some time to the main thread if i
is 200000 400000 600000 800000 to handle some button events.

The only thing what can be done is writing a faster loop ? , I don't see how this
can be done in B4I , is objective c quicker ?
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The DoEvents based code is equivalent to this:
B4X:
Sub Calc(index As Int)
   Dim value As Byte
   Dim last As Int = Min(index + 200000, array1.Length - 1)
   For i = index To last
     value = array1(i)
     If value < 6 Then value = 0   
     If array2(i) + value  < 75 Then
       array2(i) = array2(i) + value
     Else
       array2(i)=75
     End If
   Next
   Log(i)
   If i < array1.Length Then CallSubDelayed2 (Me, "Calc", i)
End Sub

You need to call Calc(0) to start.
I made array1 and array2 global variables. You can use a Type that holds the arrays and index instead.

Note that if you modify the sub and run it in debug mode then it will be very slow. Click on Ctrl + P to clean the project and it will be fast again.
 
Upvote 0

joop

Active Member
Licensed User
Longtime User
Thanks erel indeed it's faster to put the "do events" part out of the for next loop.
But the loop of course still blocks the button inputs.

Is there a faster way to add the content of a large array1 to the content of a large array2.
without a for next loop. ?

Maybe Arm assembly can make it faster , this simple loop must be very fast in assembly.
I 'll try to find some info.
 
Upvote 0
Top