Force Progress Bar to refresh?

In my console program I use two progress bars. Each time I update their Value properties, I issue a refresh (as in

ProgressBar1.Refresh ProgressBar2.Refresh
Sometimes the change shows up on the display, and sometimes it doesn’t. Is there any way to force it to show up every time? I suppose I might do it with some sort of time delay, but I don’t want to.
I have tried adding Window.Refresh with both True and False for the parameter, and that helped a bit, but not entirely.


try that…

Skip App.DoEvents
DoEvents should really really have been limited to certain kinds of console apps as almost everywhere else it can eventually cause you grief.
There’s a really limited number of cases in a GUI program where it can be used safely.

(Noting the other responses, and just explaining what is happening under the hood)

This is an excellent example of what has been noted much elsewhere in REAL/Xojo forums and blogs.

Computers - and reality - do not multitask. Ever. One thing can do only one thing at a time. That’s how God created the world - one cause, one effect. (However, you can have things go so fast they APPEAR to be simultaneous.)

The issue with Refresh or Invalidate - if there is one - is the way Xojo chooses - also in coop with the OS - of what happens in what order. I’ve noticed that at times the UI updating doesn’t happen until a function-at-hand completes. That is when Xojo-or-OS may decide to update the UI. But not all the time. A function can be CPU intensive or it can be light on work. How these affect UI updating is too complicated to be practical knowledge.

Norman’s right about App.DoEvents, however it does help smooth out the issue - you get to interfere with the processing order in a very crude way. But the cost is safety - use it at your own peril and if it gets you in trouble, nobody will help you. =) Personally I commonly never use it, but I do a couple times where I could not find any other remedy. I’m not giving up though, if I can find a “legal” remedy I’ll take that.

AFAIK this concept is key to getting a feel on how to program Xojo where the look of your app (as far as UI updating) appears so as to satisfy you - and hopefully your users.

I sum it up this way. Whenever you type App.DoEvents, ask yourself “Do I want to rewrite this code in the future?”

Except while writing your event loop in console apps, of course.

I sum it up this way. Whenever you type App.DoEvents, ask yourself “Will it last until Xojo comes with a threadsafe framework?” :frowning:

Huh? It has nothing to do with thread safety.

no? Why do you get errors like updating UI from thread not allowed?

Because the OS UI framework is not thread safe - that has nothing to do with us - we use what we’re given.
Nor does it have anything to do with why DoEvents is nasty.

You DON’T want to us DoEvents because it quite literally causes a new main event loop iteration to run which can cause all kind of reentrancy issues so you can get new events in things that are already running events and then you use DoEvents again and … yeah

Bad Things™ happen

There are maybe a couple places in a GUI program where it is safe.

If you stick to the rule “Use it only in Console apps” you won’t cause yourself issues.

Ok, Norman, thanks for the explanation. I had the idea the doevents just were a way of yieldtoamainthread kind of thing. Obviously lack of reentrance in the framework is a weakness of the framework then.

It’s not nearly as mysterious as this. Or complicated. The rule is simple. Everything running in the main thread processes linearly and nothing happens to the UI until it completes. If you want the UI to update while your code is running, put your code in a Thread.

Most of it is already reentrant.
Its just that YOU can tie yourself in knots when it happens.

A great example is in sockets where if you use doevents in an event handler for received data you can then get another data received before you’ve finished and so you now have an out of sequence error in the flow of your code

There’s no problem from the framework side.

But your code is broken in its design.

I only added app.doevents because I’ve encountered some instances where refresh/invalidate do nothing unless it’s used… Very rarely. . But yes avoid it at all costs if possible in gui apps

Using App.DoEvents to force a refresh is definitely the wrong way to solve the problem. Been there, done that.

I don’t want to make this post go on and on, but I don’t agree - certain things (and it’s not predictable) happen at different times. The OP’s issue was a great example. According to Tim’s thinking, the .Refresh or even .Invalidate should do nothing until all calling functions end in scope. But this is not what happens - .Refresh within a function often updates BEFORE the function ends. But not all the time. So then, you try to put the .Refresh in a Timer, and fire the Timer. That can work, sometimes it’s 100%, sometimes not. Supposedly you get 100% results by using a Thread - okay, I haven’t proof-tested it, but say that works. But then you hit the Law of Diminishing Returns - do you really want that many pre-designed objects all over the place, when.Refresh would/should do the trick?

This is the complication that I’m referring to.

I bring up Visual Basic all the time when I talk about this - VB is not liked by some around here - but that was one thing it did really well. .Refresh DID refresh in real-time, without any problem. You have to admit this is common sense - .Refresh really is just a function call, and it should do the work of repainting what is being Refreshed, and then it returns control back to the calling routine. There’s no dependence on Threads or Timers or anything, nor should there be. It all takes place in one thread, the Main Thread. The UI works in the Main Thread. Calling .Refresh orders it on it’s own, explicitly. Refresh. Now. And it’s 100% reliable about it. (Real/Xojo often refreshes right away, but not all the time.)

I still don’t completely understand why REAL/Xojo doesn’t work that way, but I’m not here to complain about it, just to explain.

[quote=58064:@Garth Hjelte]
I still don’t completely understand why REAL/Xojo doesn’t work that way, but I’m not here to complain about it, just to explain.[/quote]
The fact they share some common syntax is mostly good planning on the syntax that Xojo would use / support but beyond that they aren’t the same in almost any other respects

I mis-wrote my original question – my application is desktop, not console. Does this make a difference? Because I’m getting the impression that I can’t force the display to be updated.

Not really. There are only a small handful of situations where using a Refresh call is correct. Usually, Invalidate is correct.

A thread+timer setup is your solution. I won’t deny doing so can be tedious, but it’s really the only “right” way to do it. Anything else is trying to work against the framework.

I cannot get my label text displayed below the ProgressBar.

The text says something like: “Please wait while…” the things goes to an end, in say, an import, export or convert data in a loop".

That is why I draw a “progress bar” of my own: I update the Label in the loop and it is displayed.

For what it’s worth, I tried using a thread/timer approach and could not get it to work – probably because I’ve never used a thread before. HOWEVER, that effort led me to a no-thread scheme that seems to work just fine for this program. Here’s some pseudo-code for the method. Timer1 is defined with Mode initially Off and Period 250.

(After initialization there is a first call to DoTheWork)
[b]DoTheWork method:[/b]
        do an increment of work
        Timer1.Mode = Timer.ModeSingle
        If all work is done Then call EndOfJob
        update the progress bar
        prepare the next increment of work
        update a Label if appropriate
        call DoTheWork