For me, one of the must frustrating things to program for in XOJO is the Progress Bar. I’ve read all the documentation, looked at examples, etc…I just can’t ever to get it to work right. Even using Threads, it eithers performs the same way it does without the Thread, or I get Thread UI errors, depending on what I’m trying out.
Usually, I’m fine with just an indeterminate Progress Bar in my app. But even here I’ve had to resort to putting it on another windows and hiding the main one showing the new one (with the progress bar), then hiding it when my process is over. This is really janky to me, and I’d like to finally be able to have an indeterminate Progress Bar in my main window.
So, what I’m asking for help on today is pretty simple. I have a shell script I’m running that can vary in it’s time to complete. When the user clicks the action button, I want the Progress Bar to go to Indeterminate while the synchronous shell script is running, then turn that to false after the script completes.
In its most basic form, the code looks like this.
dim s as new shell
dim space as string
s.TimeOut = -1
s.ExecuteMode = shell.ExecuteModes.Synchronous
s.execute ("Powershell DO SOMETHING HERE")
What’s the best way to accomplish this?
To get the UI to update you need to use asynchronous event driven techniques. You need to show the progress bar, wait an event loop so the system will draw your UI changes, do your long process, optionally wait another event loop for good measure, and then hide your progress bar.
How you do this differs depending on what you’re doing, so tell us what you’re actually trying to do. If you’re providing a shell example, but you’re really using a thread, advice provided by the community might not actually help.
For the shell example, use an Asynchronous shell and use the
Completed event to know when it’s done.
The window will have some options on it for the user. When this is all selected, they will click on an action button which will perform a Powershell copy script. The toolbar will be on that main window.
The code I shared earlier is currently in the action event for that button.
I’ve had no luck using threads.
I tend to use a 0ms Timer to push the start of a long process to the next event loop. I can whip up an example for you.
I did recently find out that async shells can lock up your Xojo app waiting for a command, but we still can get the progress bar to show before this whole thing starts.
An example based on something similar to what I’m trying would be great! I’m obviously having trouble getting my head around the direct documentation.
Here’s a small sample project to illustrate the technique: Download relay.xojo_xml_project
I had a weird time trying to get timeout to work on Windows. When I tried a command I found that used powershell to do so, the
Completed event never occurred. I mention this because you mentioned powershell. I spend more time on Mac than Windows, so I’m not entirely sure if this is going to raise problems for you. I just wanted to call it out so you can be ready.
Definitely not acknowledging the the Powershell script has finished. It then was running multiples of my PS script. Very weird.
The only way I’ve gotten XOJO to realize PS scripts are done is to use Synchronous mode.
Can you not use Synchronous with a progress bar? Seems that’s what Synchronous was intended for.
Yeah you can use the timer technique in a similar way with a synchronous shell. Updating the UI before starting the procedure is the key to getting the progress to show. Hiding the bar when it’s done is more straightforward.
Try moving the code in the Completed event to after the Execute command in the Timer. Then change the Shell mode to Synchronous in the properties pane.
That doesn’t work either. My entire window locks up and none of the controls work before one can even click the action button.
I’m going to get screams about this, but it works in a top-down, functional approach like yours.
Well that seems weird, did you accidentally change something about the timer? It needs to be Mode: Off or it’ll fire when the Window opens.
Don’t you think that will never end because asynchronous mode doesn’t raise the Completed event? It’s untested, but I’m thinking
IsRunning would never end up false?
Wow! This works great, and exactly how I would expect it to! I’ve stressed tested it on several large file copies, and it always finished when the file copy finishes. Curious, why would someone disapprove of this method?
DoEvents destabilizes your program in unpredictable ways.
Interesting that IsRunning can end up false, but Completed never occurs.
Look up doevents in the docs.
Just reading up on it. Some are against it, some swear by it.
I’m seeing zero issues here. I’ve been stress testing it.
If it’s working for you that’s great
Powershell isn’t really something I’m familiar with. I don’t know how else to help, so I’d go with the working solution!
I appreciate your help and the time you gave me today!
Nope because we’re not creating a Shell Class, so no events are active. This is like old style functional top-down programming. That’s also why DoEvents doesn’t cause issues.
What does doEvents do in this case then? Anything at all? Could it actually be removed?