Progressbar wrong using?

Hi all.

I have a Listbox that I parse in order to Generate a PDF File for each row in Listbox.
Nothing problem is there.

The next is that I want to create a Progressbar, ignorer to know the percentage of the PDF Generation Process.
As you can see I have a label that reveals these percentage. And It works going 0% to 100%

When the current row equals the total of rows, then It shows a Message “PDF’s Generation process succesfully”
The problem becames in the progress bar, I dunno If I’m doing something wrong or what did you suggest.

Because the Progressbar doesn’t work (IN MAC).
IN WINDOWS I CAN SEE THE PROGRESSBAR SUCCESSFULLY
It doesn’t reveal the status progress, When it comes to the end, So the Bar gets full.


That is the code that I’m using:

//Total de Facturas del Listbox
Dim TotLista As Integer = listafacturas.listcount

for i as integer=0 to listafacturas.listcount -1

'Msgbox str(i+1)

//Damos valor a la barra de progreso
'Progressbar1.Value = Percentage
Progressbar1.Maximum = 100
Progressbar1.Value = (i/TotLista)*100
Progressbar1.Refresh




CFDiUUID = listafacturas.CellTag(i, 0)

'Msgbox CFDiUUID
ImprimePDFs(CFDiUUID) 

//Este es el valor de porcentaje procesado
//Lo obtenemos dividiendo el item procesado entre el total de filas
//de la lista, el resultado lo multiplicamos por 100.
//Y el resultado de esta operacin le sumamos "1"
Dim Percentage as Integer = ((i/TotLista)*100)+1


//Y asignamos el valor al rtulo de porcentaje
lblPorcentaje.text = str(Percentage) + " % PDF Generados"
lblPorcentaje.Refresh


If i+1 = TotLista Then
  Msgbox "PDF's Generation process succesfully"
  lblAvanceImportacion.text = ""
  lblAvanceImportacion.Refresh
  
  lblPorcentaje.text = ""
  lblPorcentaje.Refresh
  
  Progressbar1.Value = 0
End If

Next

Put your code in a thread and use a timer to update the bar.

I have this code inside a Button Called “Generate PDF”, when I click it, Generate all the PDFs of the items in the present Listbox.

So I understand this, pls, correct me If I’m wrong.

  1. Put my code in a thread
  2. In the button that I have I will invoke a Timer that invokes my code? Or Timer only controls the update bar?

Thanks

  1. In the button invoke the thread. The thread can invoke a single-shot timer to update the progress bar as needed. Or the button can invoke a Timer to monitor the thread and update the bar, but it’s better to do it the other way.
  • Add a timer, make it off in the IDE, period 0.
  • Add a property to the page ProgressValue as Integer

If you want to set anything in the ProgressBar such as maximum, do it in the button.

Then modify your code in the thread as follow :

//Damos valor a la barra de progreso ProgressValue = (i/TotLista)*100 Timer1.Mode = Timer.ModeSingle

In the Timer Action event :

ProgressBar1.Value = ProgressValue Progressbar1.Refresh Me.Mode = Timer.ModeOff

I don’t thing the refresh is necessary, but it does not hurt.

Sorry for my newbieness.

1)I created the Thread in the IDE.
2)In RUN’s event I pasted my code.
3) In the Button, for run the thread. I do this: ThreadPDFS. Cuz I put this name.
but it says that I need to use the returned function.

So, I used call ThreadPDFS
What Am I doing wrong?

Thanks

The LR is your friend :
http://documentation.xojo.com/index.php/Thread.Run_method

[quote=253328:@Michel Bujardet]- Add a timer, make it off in the IDE, period 0.

  • Add a property to the page ProgressValue as Integer

If you want to set anything in the ProgressBar such as maximum, do it in the button.

Then modify your code in the thread as follow :

//Damos valor a la barra de progreso ProgressValue = (i/TotLista)*100 Timer1.Mode = Timer.ModeSingle

In the Timer Action event :

ProgressBar1.Value = ProgressValue Progressbar1.Refresh Me.Mode = Timer.ModeOff

I don’t thing the refresh is necessary, but it does not hurt.[/quote]

Hi Michael, I done what you said me,

  1. I’ve done a Timer, with period = 0, mode single in the IDE.
  2. In the Timer (Called “UpdateTimer”) on Action’s event I do this:

ProgressBar1.Value = ProgressValue Progressbar1.Refresh Me.Mode = Timer.ModeOff
3) I’ve made a Thread and Inside the thread I’ve pasted my code.
4) I’ve created a ProgressValue as Integer property, and modifying the code in the thread as you told me
4) In Action Button’s Event I run the Thread as this: TheadPDFs.Run.

So the code in the Thread is the following:

[code]'Dim folioFiscalUUID As String = listafacturas.Cell(listafacturas.ListIndex, 0)

//Leemos el Listbox y contamos cuantas filas tiene para decirle a lblTotal cuantas facturas muestra la lista
Dim CFDiUUID As String

//Total de Facturas del Listbox
Dim TotLista As Integer = listafacturas.listcount

for i as integer=0 to listafacturas.listcount -1

//Damos valor a la barra de progreso
ProgressValue = (i/TotLista)*100
UpdateTimer.Mode = Timer.ModeSingle

'mProgressValue = ((i/TotLista)*100)+1
'Msgbox str(mProgressValue)


'Msgbox str(i+1)

//Damos valor a la barra de progreso
'Progressbar1.Value = Percentage
//Progressbar1.Maximum = 100
//Progressbar1.Value = (i/TotLista)*100
//Progressbar1.Refresh




CFDiUUID = listafacturas.CellTag(i, 0)

'Msgbox CFDiUUID
ImprimePDFs(CFDiUUID) 

//Este es el valor de porcentaje procesado
//Lo obtenemos dividiendo el item procesado entre el total de filas
//de la lista, el resultado lo multiplicamos por 100.
//Y el resultado de esta operación le sumamos "1"
Dim Percentage as integer = ((i/TotLista)*100)+1


//Y asignamos el valor al rótulo de porcentaje
lblPorcentaje.text = str(Percentage) + " % PDF Generados"
lblPorcentaje.Refresh


If i+1 = TotLista Then
  Msgbox "Generación de PDF's masiva finalizada con éxito"
  lblAvanceImportacion.text = ""
  lblAvanceImportacion.Refresh
  
  lblPorcentaje.text = ""
  lblPorcentaje.Refresh
  
  Progressbar1.Value = 0
End If

Next[/code]

But, When I click the button to Run, I give this Error: ThreadAccessingUIException

Pointing to: Dim TotLista As Integer = listafacturas.listcount
That I use to know the total of items present in the Listbox.

What Am I doing wrong?

You cannot address ANY UI control. Move all that to the timer :

[code]Msgbox “Generación de PDF’s masiva finalizada con éxito”
lblAvanceImportacion.text = “”
lblAvanceImportacion.Refresh

  lblPorcentaje.text = ""
  lblPorcentaje.Refresh
  
  Progressbar1.Value = 0[/code]

[quote=254271:@Michel Bujardet]You cannot address ANY UI control. Move all that to the timer :

[code]Msgbox “Generación de PDF’s masiva finalizada con éxito”
lblAvanceImportacion.text = “”
lblAvanceImportacion.Refresh

  lblPorcentaje.text = ""
  lblPorcentaje.Refresh
  
  Progressbar1.Value = 0[/code][/quote]

I’ve done this, even I saw that 'Dim TotLista As Integer = listafacturas.listcount and 'for i as integer=0 to listafacturas.listcount -1 makes crash, I think to make a property for each one assigning the respective value in the Button,not in the thread, then Use the value in the thread.

But already have problem with this; CFDiUUID = listafacturas.CellTag(i, 0)

Also I tried doing this in a button for passing the value to the thread:

[quote] For i As Integer = 0 to listafacturas.listcount -1
CFDiUUID = listafacturas.CellTag(i, 0)
ThreadPDFS.run[/quote]

But Its useless, All points to UI controls in my code.

No UI element can be accessed from a thread. So either don’t use a thread, or use timers to access the UI.

The entire If i+1 = TotLista Then block can be moved to a timer, as I see it. It is not that difficult to do.

Your choice.

To keep in mind for next time, try using a listbox only to present data. Not to store/manipulate data.
Because your data is sitting in a listbox, you can’t access it from a thread.
For this (and many more reasons) I find it easier to use data in structures (or if it’s a lot, a DB).

[quote=254308:@Marco Hof]To keep in mind for next time, try using a listbox only to present data. Not to store/manipulate data.
Because your data is sitting in a listbox, you can’t access it from a thread.
For this (and many more reasons) I find it easier to use data in structures (or if it’s a lot, a DB).[/quote]
BINGO!, I thought you gave me an Idea!.

When I display the data on the listbox also Store the same data on a Multidimensional Array.

I suppose that Arrays are accesible through Threads Right?

Correct me If I’m wrong

yes.

(And if I really need call methods outside a thread that accesses the UI, I use CallLater singleshot timers)

“Problem” is, GUI elements can’t be altered within a thread. Instead of, set the values of global variables in the thread, and let a Timer read the variables to update the GUI element finally.