Threads and GUI exception problems

I have to process large (time consuming) loops in which I need to access GUI elements for reading and creating canvas and other controls at the fly, not actually showing them but accessing.
I know how to use Task and update the interface but I need to process the GUI elements in the thread or be able to show a progress bar in another way.

DoEvents worked fine but I learned (the hard way) not to use it as I got some weird bugs with them.

While running the app in debug mode it updates my progress bar (a canvas subclass with an update method because refreshing a progress bar doesn’t works) without using DoEvents or threads but once compiled it doesn’t works.

Wouldn’t it be possible to use a similar technique to the one XOJO uses in debug mode for updating the GUI?

A thread cannot access the UI. Your choices are to use a Timer to update the UI based on information it gets from the thread or to use the Task class. See Threading in the User Guide.

Paul,

thanks but I can’t thread the process, it must have access to the UI and this raises an exception; therefore Thread or Task are not usable.

Any info about why it works in debug mode?

Instead of using loops, use timers with period zero.

Loop :

For n = 1 to 1000 //... next

Timer

Static n as integer If n <= 1000 //... n = n+1 else me.mode = Timer.ModeOff end if

No need for doevents at all.

I really question this. I’ve yet to find anything that can’t be threaded. I use the Task method to update UI all the time. Not hard to use either.

DoEvents is evil. If you think you want to use DoEvents in a desktop app you need to look at threads instead.

Michel,
not sure to understand you: I should start the timer n times in the main loop and at the timer update the progress bar?

Bob,
if you try to read a rectcontrol.width in the thread you will get an exception; and I can’t read it before because they are “virtual” controls changing in the loop itself. At the end of the loop I refresh the UI but I need to access it also from the loop itself.

Btw, I have found why it works in debug mode: 32 bits. Also compiled in 32 bits it works fine but not in 64bits.
Following code:

Dim progressValue As Integer
While progressValue < 100
    progressValue = progressValue + 1
    Dim waitUntil As Integer = Ticks + 15
    While Ticks < waitUntil
    Wend
    ProgressCanvasClass1.UpdateMe(progressValue,100)
  Wend

with ProgressCanvasClass1 being a subclass of canvas and an UpdateMe method to refresh itself (at the Paint event it uses the progressvalue to draw a rectangle).

Doesn’t updates the canvas in 64 bits but it does in 32bits.

There are ways to get around these issues. Have a timer put the values you need from the RectControl in properties that that the thread can read.

[quote=269393:@Alejandro Fresno Meyer]
Bob,
if you try to read a rectcontrol.width in the thread you will get an exception; and I can’t read it before because they are “virtual” controls changing in the loop itself. At the end of the loop I refresh the UI but I need to access it also from the loop itself. [/quote]
You are relying too much on the UI for data storage. You need to do all your data processing separate from the UI and send notifications to the UI as necessary (or wait until the end of the thread.)

I tried to give you examples. In your code the While/Wend freezes the UI because the event or method into which it stands does not terminate. If instead you place that code in a Timer the UI won’t be frozen because the Action event will terminate at each iteration.

For instance, instead of the cumbersome WaitUntil while/Wend, drag a timer onto your window, let us call it TimerProgress, set it to off, and place this in the Action event :

Static progressValue As Integer If progressValue <= 100 progressValue = progressValue + 1 ProgressCanvasClass1.UpdateMe(progressValue,100) else me.Mode = Timer.ModeOff ProgressValue = 0 End if

Then wherever you had placed your original code enter

TimerProgress.Period = 255 (15*17ms, one tick ? 17ms ) Timer.Progress.Mode = Timer.ModeMultiple

You should NEVER use a While/Wend to pause execution. It devours CPU, it freezes the UI, and is a remnant of 20 years old procedural programming. Instead, use a timer. In an event driven programming language such as Xojo, that is the normal way.