Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF optimize loading on the UI thread

I am trying to optimize the loading times for my WPF prism application. The loading is basically a loop of using reflection to create instances of UI elements and then adding them to the main window (the shell) in a tab control.

Since we are limited to using a single thread to create all the objects, what would be the optimal way to speed up loading / create a better user experience?

These are the options I have so far:

  1. Use lazy loading. Only load the tab when the user first clicks on it. But that would have a 4-5 second delay opening the first time as it gets initialized on demand.

  2. Cache all the reflection calls. I actually did that, but it did not speed anything up at all. Most of the time occurs during the rendering of the controls...

  3. ?

Any suggestions would be greatly appreciated for this tricky problem.

like image 807
gchen Avatar asked May 15 '26 22:05

gchen


1 Answers

You're pretty much stuck as you can only load objects on the main thread, so I don't think you'll make it load any faster.

What you can do is distract the user: I have an animated splash screen that take about 10 seconds to work its way through the animation sequence. This serves a number of purposes:

  1. It shows the user motion - so they have a visual cue that something is going on
  2. It distracts them and fills the space taken by the initial load

To ensure smooth animation you need to create a second dispatcher. Here's how I do it:

public class AppEntry : Application
    {
        private static ManualResetEvent _resetSplashCreated;

        internal static Thread SplashThread { get; set; }

        internal static SplashWindow SplashWindow { get; set; }

        private static void ShowSplash()
        {
            SplashWindow = new SplashWindow();
            SplashWindow.Show();
            _resetSplashCreated.Set();
            Dispatcher.Run();
        }

        [STAThread]
        public static void Main()
        {
            _resetSplashCreated = new ManualResetEvent(false);
            SplashThread = new Thread(ShowSplash);
            SplashThread.SetApartmentState(ApartmentState.STA);
            SplashThread.IsBackground = true;
            SplashThread.Name = "Splash Screen";
            SplashThread.Start();

            _resetSplashCreated.WaitOne();

            var app = new App();
            app.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(app_DispatcherUnhandledException);
            app.InitializeComponent();
            app.Run();

        }

        static void app_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
           // MessageBox.Show(e.Exception.StackTrace);
        }
    }

I set the AppEntry class as my Startup Object in the Project Properties/Application tab.
I close my splash screen at the end of my OnStartup method in App:

 AppEntry.SplashWindow.Dispatcher.BeginInvoke(DispatcherPriority.Background,
                                                             new Action(() => AppEntry.SplashWindow.Close()));

Is this faster? No Does the user think it's faster? Yes

Sometimes, if you can't give them speed, you can give them activity. It's a nice placebo.

like image 95
Faster Solutions Avatar answered May 19 '26 03:05

Faster Solutions