How to speed up loading screensavers

I am optimizing the launch of the WinForms application. One of the problems that I have identified is loading the splash screen form. It takes from a half seconds to a second.

I know that multithreading is a no-no part of the user interface, however, seeing how the screen saver is a fairly autonomous part of the application, is it possible to somehow soften its performance by throwing it into some other thread (maybe the way Chrome does it), so important parts of the application can really evolve.

+7
c # visual-studio-2008 winforms splash-screen
source share
6 answers

The .NET platform already has very good splash screen support in Windows Forms applications. Check out this thread for sample code. It is really optimized for a warm start-up time, it provides the start and start of a stream spike and start before the initial application is initialized.

+9
source share

Nothing comes of spawning a thread if your goal is to get a splash screen as quickly as possible.

There are several ways to make screensavers, and the more complicated one is mentioned here , but this is a simple method that I used with complete success:

Just make sure you download and display the splash form first , and then continue to download your application while the user looks at the pretty splash screen. When mainform is loading, it can close the splash right before it shows itself (an easy way to do this is to pass the splash shape to the main form in your constructor):

static void Main() { Application.SetCompatibleTextRenderingDefault(false); SplashForm splash = new SplashForm(); splash.Show(); splash.Refresh(); // make sure the splash draws itself properly Application.EnableVisualStyles(); Application.Run(new MainForm(splash)); } public partial class MainForm : Form { SplashForm _splash; public MainForm(SplashForm splash) { _splash = splash; InitializeComponent(); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); // or do all expensive loading here (or in the constructor if you prefer) _splash.Close(); } } 

Alternative: If you prefer not to pass the burst to MainForm (perhaps this seems inelegant), then subscribe to the MainForm Load event and close the splash screen there:

 static class Program { static SplashForm _splash; [STAThread] static void Main() { Application.SetCompatibleTextRenderingDefault(false); _splash = new SplashForm(); _splash.Show(); _splash.Refresh(); Application.EnableVisualStyles(); MainForm mainForm = new MainForm(); mainForm.Load += new EventHandler(mainForm_Load); Application.Run(mainForm); } static void mainForm_Load(object sender, EventArgs e) { _splash.Dispose(); } } 

As mentioned in this thread , a potential drawback of this solution is that the user will not be able to interact with the screensaver. However, this is usually not required.

+3
source share

Yes.

You need to create a new STA thread that shows the splash screen with Application.Run , then call Close with Invoke after the main form is ready (in the main thread).

EDIT : For example:

 static SplashForm splash; Thread splashThread = new Thread(delegate() { splash = new SplashForm(); Application.Run(splash); //Blocking call on separate thread }); splashThread.SetApartmentState(ApartmentState.STA) splashThread.Start(); LoadApp(); //In MainForm_Shown: splash.BeginInvoke(new Action(splash.Close)); 

For optimal performance, you should make your Main method show the splash screen, and then call the separate method that loads the application. Thus, all assemblies will be loaded after the splash screen is displayed. (When you call a method, JITTER will load all the types that it uses before starting the method)

+1
source share

Multithreading in WinForms is fine as long as all user interfaces remain in the same thread.

This is how screensavers are usually made. Important work is done in the background thread, while the splash screen is displayed in the user interface thread so that the user knows that the rest of the program will appear in the near future.

After important material has occurred, raise an event so that the user interface thread knows that it is time to hide the screensaver (just remember to marshal the event handler using Invoke () back to the user interface stream to close the screensaver).

+1
source share

The answer to the question of perception. There are various methods, NGEN is assembling, putting things in the GAC, but what you need to understand is what really happens.

C # takes time to load a virtual machine, load prefabricated assemblies and load assemblies based on what is on this splash screen. And then it still takes some time from the cold start to start the first screen.

This is due to the JIT compilation that occurs the first time you access the screen.

The strategy I use is a traditional lightweight pop-up page that loads quickly, so it is visible, but in the background I create a stream and load an invisible form. This form has all the controls that I intend to use, and so the JIT compiler does its work and loads the assemblies. This creates the illusion of responsiveness on the small side. Time taken to launch + visible pop-up page + pause + time to click the 1st option, more time needed to complete the flow, and then clean and upload the form.

Otherwise, applications seem clumsy and slow for users on first launch. Warm screens start up much faster because builds and JIT are complete.

+1
source share

We do this by providing a tiny little native C ++ application that serves as a screensaver.

Then follows this process:

  • The user double-clicks on the application icon.
  • A C ++ application launches displaying the splash bitmap as WS_TOPMOST.
  • A C ++ application launches the main C # application.
  • The C # application will start, and finally, notifying the C ++ application (via a simple file), exit it.
  • C ++ application shuts down.

The C ++ application also has a timeout (in the event of a C # application crashing) and automatically terminates if it does not receive an exit notification within 30 seconds.

This approach has its drawbacks in that you cannot attach the application to the taskbar. If you bind a C ++ application (which is the main application for the end user), you get another task in the taskbar because the C # application is different. I think I could solve this by providing settings in the application manifest of both C ++ and C # applications to tell them that this is the β€œsame” application in terms of the taskbar.

+1
source share

All Articles