Possible scenarios for using Yield other than fixed interval

Hello,

I use yield inside loops to avoid application freezing by applying

if (ctr % interval)=0 then yield.

but sometimes the process inside the loop could take long time, like in some loops interval could be 1000 and it is ok and in some other loops even 10 is not ok.

So is there a way to let the application execute the Yield when necessary only.
I tried Lost Focus and Gain Focus and timer but none of them worked.

Regards

Try changing the interval to be a time span vs n times through the loop

An alternative is to make the loop code be driven by a Timer Event in an Accept loop. This link is to a hand coded one in the Boxsoft Invoice Example TestDev APP you can download and use:

Below I’ll try to paste the code, it is cut from a few places:

RecordsBefore   LONG
RecordsAfter    LONG
ToDoRecords     LONG
RecordNo        LONG
Progress:Thermometer    LONG 
Progress:New            LONG
RecordsPerCycle         LONG
ProgressFACTOR          REAL 
ProgressWindow       WINDOW('Add Test CustomerCompany'),AT(,,142,59),FONT('Segoe UI',9,,FONT:regular),DOUBLE,CENTER,GRAY,MDI 
                       PROGRESS,AT(15,15,111,12),USE(Progress:Thermometer),RANGE(0,25)
                       STRING(''),AT(0,3,141,10),USE(?Progress:UserString),CENTER
                       STRING(''),AT(0,30,141,10),USE(?Progress:PctText),CENTER
                       BUTTON('Cancel'),AT(46,42,49,15),USE(?Progress:Cancel),SKIP
                     END
   CODE
...
AddTestDataRtn ROUTINE
    ?Progress:UserString{PROP:Text}='Add ' &  ToDoRecords    
    ProgressFACTOR = ?Progress:Thermometer{PROP:RangeHigh} / ToDoRecords
    RecordsPerCycle = 25
    RecordNo=0
    0{PROP:Timer}=1
AL: ACCEPT
       CASE EVENT()
       OF EVENT:Timer
            LOOP RecordsPerCycle TIMES
                 IF RecordNo >= ToDoRecords THEN BREAK AL: .
                 RecordNo += 1
                 DO AddOneRtn
            END
 
            !Update the window slows things so only do it when the % changes 1 segment, in this case 1 of 25
            Progress:New = RecordNo * ProgressFACTOR
            IF Progress:Thermometer < Progress:New THEN 
               CHANGE(?Progress:Thermometer,Progress:New) 
               ?Progress:PctText{PROP:Text}=RecordNo &' done'
            END 

       ELSE             
          IF ACCEPTED() = ?Progress:Cancel THEN 
             IF Message('Cancel Process?','Add Test Data',ICON:Cross, |
                        'Cancel|Continue',2)=1 THEN BREAK.
          END 
       END !Case Event 
    END  !Accept      
    0{PROP:Timer}=0  
1 Like

I will check that.

Thank you

I will try to implement this.

Thank you

:+1: :+1: :+1: to Carl

I use this approach whenever possible. It pretty much eliminates an app going unresponsive.

I think it a smart idea, I wrote this code and it gave much better response.

Regards
** sorry I had to set an image but I am having problem with TABs/Spaces to align the code in this editor that simply I coudn’t do it :pensive:

tm1=clock() ! Initialize the variable tm1 with the current clock time.

loop
  !........... My Long Process
  if clock() >= tm1+100*30 ! Check if 30 seconds have passed since the last time tm1 was set.
    yield
    display(?list1)
    tm1=clock() ! Set tm1 to the current clock time.
  end
end