Splash Screen Control Issue

After researching the forums for an answer to splash screens issues, I’m still lost as to how to keep my progress bar moving in the splash screen

I initially started by making the splash screen the main window. It opens and initiates two timers. One to increment the progress bar and one to call my main app in another window for a startup sequence which takes about 15 seconds cycling dampers, gathering temperature reading, loading data, etc. The progress timer in the splash screen does as it should, incrementing the progress bar but when the timer for the startup sequence in another window is called the progress bar stops while the startup sequence completes its task.
When the startup sequence finishes the other window opens which closes the splash screen as desired.

I have since experimented with a thread but when I attempt to increment the progress bar from the thread an error tells me the thread can not manipulate a window control.

How might I keep the progress bar incrementing after the startup sequence is initiated in the other window?

You could still use a thread, but the way to do the progress would be to have the thread set a property somewhere to indicate progress and use a Timer to check that value periodically to set the progress bar.

Also, don’t forget to call thread.sleep periodically to give the rest of the app a chance to run things.

So the thread does not directly manipulate the progress bar directly. I would think I’d have the same problem with the timer that checks the property since the timers seem stop updating the progress bar. What would the thread accomplish since I would still be using timers outside the thread to check the property?

The thread yields time to the app so it can draw.

So are you thinking the timers to update the progress bar should be located in the main app and not the splash screen?

Rather an invigorating journey to make this one work. The problem was keeping the progress bar moving while loading configurations.
The end solution was to add a thread to the splash screen which as Greg might say to do all the heavy lifting. All of my time-consuming startup routines were place in the thread. I had to remove some items that referred to GUI controls. I may have been able to use Thread.UserInterfaceAdd and Update but I don’t understand how to use them yet. All the items that needed to be updated in the GUI were placed in a method that was called from a timer that was set at the end of the thread’s job list. Interesting that you can call a thread that is in the GUI from the thread. It worked, updating the GUI, starting a sequence timer for the normal operation of the main window, and then closed the splash screen to bring the main screen live. Voilà

Open for refinements?

1 Like

A lake in the splash screen, great idea :wink:.

You’re not actually doing that. The thread starts the timer and exits. The timer is completely separate from the thread. The thread ends and a few milliseconds later the timer fires in the main (GUI) thread and updates the UI. This gets around the rule that a thread cannot update the UI by delegating that update to a separate object that runs in the GUI.

I think you read between the lines, I did mean the tread calls a timer. I guess this was a resonable approach.

I’m starting to play with Json files in conjunction with dictionaries. Would converting a DateTime to DateTime.SecondsFrom1970 be the correct approach for saving with Json? I’m not sure it will save a raw DateTime.

That’s one option. Using SQLDateTime values is another approach that gives you the benefit of human debuggable JSONs.

About your issues with thread.UserInterfaceUpdate: Consider the API 2.0 thread class having a built-in update timer. Every time you add something to the update dictionary with AddUserInterfaceUpdate, that timer is started with a small delay and when it fires will raise the UserInterfaceUpdate event, which you can then use to, well, update the user interface.

The reason the parameters appear in a rather unusual array of dictionaries is that it can happen that the thread calls the Update method several times before the timer finds time to raise the Update event. So you will get an array that enables you to process the dictionaries in the order they had been sent.

And the reason that method takes pairs or dictionaries is to make it versatile.
You could use
me.AddUserInterfaceUpdate("Progress":15)
to set your progress bar, or
me.AddUserInterfaceUpdate("Error":exc)
to forward an exception that the thread ran into and report the error, or whatever.

But nothing wrong with your approach. Even better: You know how it works internally. UserInterfaceUpdate just supplies you with an interface protocol and the necessary timer.

1 Like