B4J Question Progress indicator not updating

Stulish

Active Member
Licensed User
Longtime 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

B4X:
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
 

Roycefer

Well-Known Member
Licensed User
Longtime 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.
 
Upvote 0

Stulish

Active Member
Licensed User
Longtime 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
 
Upvote 0

Stulish

Active Member
Licensed User
Longtime 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
 
Upvote 0

Roycefer

Well-Known Member
Licensed User
Longtime 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.
 
Upvote 0

Stulish

Active Member
Licensed User
Longtime 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.

B4X:
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

B4X:
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

B4X:
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
 
Upvote 0

Stulish

Active Member
Licensed User
Longtime User
I have also changed the UnzipSelected Sub to use CallSubDelayed

B4X:
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?
 
Upvote 0

Stulish

Active Member
Licensed User
Longtime 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
 
Upvote 0

rwblinn

Well-Known Member
Licensed User
Longtime 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.
 

Attachments

  • B4JHowToArchiverLib.zip
    45.1 KB · Views: 244
Upvote 0

Stulish

Active Member
Licensed User
Longtime User
Thanks rob, i will take a look once i get half an hour :)
 
Upvote 0
Top