B4J Question Progress indicator not updating

Discussion in 'B4J Questions' started by Stulish, Jul 21, 2015.

  1. Stulish

    Stulish Active Member Licensed User

    Hi i have a B4J app that unzips multiple files, and i wanted to show the progress but the indicator doesn't update until the end

    Code:
    Private selection_progress_ind as ProgressIndicator

    Sub OpenZipGetFile(fn as string,perc as double)
       selection_progress_ind.visible = 
    true
       selection_progress_ind.progress = (perc/
    100)
       
    If File.Existis(File.GetFileParent(fn),File.GetName(fn)) Then
            Zip.ABUnzip(fn,tempDir)
       
    Else
            
    Log("No File: " & fn)
       
    End If
    End Sub
    The Selection_Progress_ind is added in designer so i didn't initialize, and the sub OpenZipGetFile is called for a for next loop that runs through all the files selected.

    The Progress Indicator remains empty until all of the files have been unzipped and then reports 100%.

    Any help is appreciated.

    Regards

    Stu
     
  2. Roycefer

    Roycefer Well-Known Member Licensed User

    The unzipping should be performed off the main thread if you hope to be able to execute UI changes concurrently. UI changes are sent to the end of the message queue on the main thread so they won't execute until the main thread can process messages. If the main thread is bogged down unzipping files, then the UI won't be updated until it's finished doing all that. At that point, all your calls to update the ProgressBar will be executed in rapid succession and you won't be able to see the progress. It'll look like it just snaps to 100%.

    From your unzipping thread, call unzipThread.RunOnGuiThread("progressUpdater", Array(d)) where progressUpdater is a method (that accepts an Object as a parameter which you will cast to a Double inside the method) that updates the ProgressBar. Also, make sure that your unzipThread doesn't send too many requests to update the UI too close together or else the UI will update in a jerky, unsmooth manner (or not at all). If the updating is too jerky, keep track of how long ago, in milliseconds, the last update request was sent by the unzipThread and only send another request if the last request was more than 33 milliseconds ago. This amounts to a ProgressBar refresh rate of 30 frames per second. Any faster and the human brain can't really tell the difference and you're just bogging down the UI thread for no added benefit.
     
  3. Stulish

    Stulish Active Member Licensed User

    Thanks Roycefer, you are correct i didn't do the unzipping on another thread, i will look at creating another thread for this and try out what you have said.

    Thanks

    Stu
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    You can use the Informatix Archiver library (from B4A). It supports asynchronous operations.
     
  5. Stulish

    Stulish Active Member Licensed User

    Erel,

    Thanks for the help, i used the asyncunzip function, i can see the progress value in the Logs as i output to log before chganging the progress indicator, bu the indicator remains at 0 until the end then jumps to 100%.

    is it usual for the value to be output to the log but not update the ui??

    thanks
     
  6. Roycefer

    Roycefer Well-Known Member Licensed User

    Are you sending off all the unzip jobs to be performed one immediately after the other, without waiting for completion? Or are you waiting for one to complete before starting the next (this is my recommendation)? The _UnZipProgression and _UnZipDone events execute in the main thread (even if the actual unzipping is done off the main thread) which means all the stuff I said about message queues and main threads in my previous post still applies.

    If you have 10 _UnZipProgressions arriving in the main thread message queue in rapid succession (i.e. #10 arrives before #1 has returned) and each one updates the ProgressBar, each one will be sending a message to update the ProgressBar to the end of the message queue. Which means the PB won't be updated until all those 10 events have returned and then all the PB update messages will be executed in rapid succession.

    The bottom line is you have to be aware of how fast you're crowding up the message queue in the main thread and design your algorithm to avoid overcrowding if you want the UI to update smoothly.
     
  7. Erel

    Erel Administrator Staff Member Licensed User

  8. Stulish

    Stulish Active Member Licensed User

    Hi Erel,

    Thanks for your fast responses as always, My problem is each zip file only holds one file, so i loop through each selected file to unzip, i can see the log fill up with 'Progress: ???' as it unzips each file, but the progress of the progress indicator is not updated.

    Code:
    Sub UnzipSelected()
    For a=startindex to stopindex
       
    Dim tempName as String = SortedList.get(a)
       OpenZipGetFile(tempName)
       selection_progress_ind.Progress = (a/stopindex)
       
    Log("Progress: " & (a/stopindex))
    Next
    End Sub
    Code:
    Sub OpenZipGetFile(fn as string,perc as double)

       
    If File.Existis(File.GetFileParent(fn),File.GetName(fn)) Then
            Zip.asyncunzip(
    file.GetFileParent(fn),File.GetName(fn),tempDir,"UnzipDone")
       
    Else
            
    Log("No File: " & fn)
       
    End If
    End Sub
    next i updated the UnzipProgression sub as follows

    Code:
    Sub UnzipDone_UnzipProgression(Count as Int, FileName as String)
       selection_progress_ind.Progress = currentPlay
       
    Log("Done: " & currentPlay & ")")
    End Sub
    When i run the app, i can see the 'Progress: ??' and the 'Done: (??)' Log entries increasing with each file from 0 to 1 but the progress indicator only updates once all unzipping is complete?

    If i put a break point on the 'Log("Done: " & currentPlay & ")") line, the program doesn't pause until all unzipping is complete even though the log updates each entry from 0 to 1.

    So i am still stuck.

    Regards

    Stu
     
  9. Stulish

    Stulish Active Member Licensed User

    I have also changed the UnzipSelected Sub to use CallSubDelayed

    Code:
    Sub UnzipSelected()
    For a=startindex to stopindex
       
    Dim tempName as String = SortedList.get(a)
       OpenZipGetFile(tempName)
       currentPlay = a/stopindex
       CallSubDelayed(Me,
    "updateProgress")
    Next
    End Sub



    Sub updateProgress
       selection_progress_ind.Progress = currentPlay
       
    Log("Progress: " & currentPlay)
    EndSub
    Still the update only happens at the end of every file to be zipped?
     
  10. Stulish

    Stulish Active Member Licensed User

    Hi Roycefer,

    I have only just seen your reply in between Erels, i am sending one after another without waiting for a completed, i will look at waiting for the unzip complete before sending the next sip file and see if that works.

    Thanks

    Stu
     
  11. rwblinn

    rwblinn Well-Known Member Licensed User

    Hi,

    scribbled an example (only showing unzipping) using the Informatix Archiver library (great lib = thanks to Informatix).
    To note: The handling of multiple files in the example can be optimized, but its works.
     

    Attached Files:

    Erel likes this.
  12. Stulish

    Stulish Active Member Licensed User

    Thanks rob, i will take a look once i get half an hour :)
     
Loading...