5

We are dealing with slow start for WinForm applications (it is a large application and has many control assemblies). Control assemblies are DevComponents. Ngen was applied to prevent jit compilation, but the loading time just decreased a little.

The app has a splash screen, but it appears only in 12 seconds after the app has started. Is there any approach to show the splash screen at once?

Our current suggestion is to create a lightweight app with the splash screen, run the main app in a separate process, and close the lightweight app when initialization of the main app is done.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Andrei Schneider
  • 3,618
  • 1
  • 33
  • 41

4 Answers4

12

You're never going to get a splash screen for a .NET application to show instantly. Even if you've NGen'ed the assemblies to eliminate the JIT-compile time, you still have to wait while all of the .NET Framework DLLs are loaded into memory. It's a pretty large framework, and it takes a non-trivial amount of time to load upon a cold start. Nothing you can really do about that.

Microsoft has tried to ease the pain as much as possible. The WindowsFormsApplicationBase class (it's defined in the Microsoft.VisualBasic namespace, but don't let that scare you off; it's perfectly usable from a C# application) provides a built-in mechanism for showing a splash screen. All you have to do is set its SplashScreen property to the appropriate form, and everything else is handled behind the scenes. It's been heavily optimized for maximum response time, even in a cold-start situation, but it's still not going to be instant.

The only other option that you have is to write small wrapper in unmanaged code, whose only purpose is to throw the splash screen up as quickly as possible, then call your .NET application to start launching itself. The lighter the better here, of course. C++ is an option, but C is probably a better option. You need to minimize the number of external libraries that you have to link, so a framework like MFC or Qt is definitely out: you need to target the Windows API directly.

The Visual Studio team did something similar in VS 2010. They have a pretty interesting explanation of the process available on their blog:

Even though Visual Studio 2010 uses WPF for its main window, using WPF for the splash screen would require that we wait for the CLR and WPF to initialize before we could paint a single pixel on the screen. While we’ve made some tremendous improvements in CLR and WPF startup speed in .Net 4.0, it still can’t quite match the performance of raw Win32. So, the choice was made to stay with native C++ code and Win32 for the splash screen.

But I wouldn't spend too much time here. Since you should generally give users the option to turn splash screens on and off, and most users will opt to turn it off, it's unlikely that very many people will ever see it in the first place. Any good optimization profiler would tell you that it isn't worth optimizing.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
5

For a lightweight, reusable splash screen component written in C++ and using the native Windows APIs, see Stefan Olson's splash screen. It takes the approach Cody Gray alludes to of starting with a separate non-CLR process which then loads the main CLR app.

I had to implement the exact same thing at my last job and I can confirm the approach works well -- the time between the user clicking the program icon in the start menu and the splash screen appearing is just a few milliseconds and so feels 'instant'.

Hugh W
  • 716
  • 2
  • 10
  • 33
1

I'd say go along with your current suggestion.

The Winforms app will not show unless it has loaded completely into the memory, and since it takes time, I'd suggest having a loader application which shows the splash and executes the main huge app(as a child process).

In the huge app, terminate the parent app upon load. That won't kill the child, BTW.

Dheeraj Kumar
  • 998
  • 13
  • 22
  • It's unlikely that a small WinForms app will load a form significantly quicker than a *large* WinForms app will load that same form. The idea is to load the splash screen form *first* in either case, not to start by showing the main form, and have the main form show the splash screen. – Cody Gray - on strike Apr 21 '11 at 11:41
  • Huh? A small WinForms app without any dependencies other than CLR will load significantly faster than an app with a large number of dependencies. What do you mean "start by showing the main form and have the main form show the splash screen"? Can you elaborate? – Dheeraj Kumar Apr 23 '11 at 08:25
  • 1
    Read my comments to Jason Moore's answer. The dependencies don't get loaded by the CLR until they're required. There is no penalty unless you're actually using code from those external assemblies, whether they're referenced by your application or not. What I mean is that you can show a simple splash screen form that doesn't rely on any external dependencies at the beginning of your `Main` method, and it will load just as quickly in an empty WinForms app as it will one with a hundred dependencies. Those dependencies don't get loaded until you request them, that's the magic of JIT compilation. – Cody Gray - on strike Apr 23 '11 at 08:27
0

The quick and dirty way that I have done in the past is to have two applications, your main application and your splashscreen application. The main application is normal with all of its heavyweight DLLs, controls, etc. The splashscreen application is simply an application and one Windows form, with all of the unneccesary reference DLLs stripped from the project - in fact you can take this one step further and make use a lighter weight .NET framework like the compact .NET framework or an earlier version of the .NET framework like 1.X or 2.0.

What you would do is have the splashscreen application startup and immediately show the single splashscreen. Have a Windows form timer (set for say 100 ms) and enable the timer as the last line of the form's Load event. When the timer fires, disable the timer and then launch your real application. See this discussion for how to do that. Now the main application will begin to fire up. Once the application is done with its initialization and perhaps loading the first form, then have the main application kill the splash screen application. More info on killing an application here.

Community
  • 1
  • 1
Jason Moore
  • 3,294
  • 15
  • 18
  • It's unclear how this actually improves the situation. You still have to wait for the .NET DLLs and the CLR to get loaded, even if you have a relatively small .NET app. And more importantly, the CLR is smart enough not to load assemblies/referenced DLLs that you aren't using. If your splash screen form doesn't use any controls defined in those reference DLLs, and it's the first thing you throw up on the screen, it will be equally as fast in a "large" application as it will in a "small" one. – Cody Gray - on strike Apr 21 '11 at 12:02
  • Also, I very much recommend abandoning the suggestion to use a timer. Users don't want to wait *even longer* for you application to load, just because you're showing them an advertising billboard. I'm not opposed to splash screens for applications that have really long loading times, but adding in a delay (even if it's only 100 ms) is so completely pointless it's almost offensive. – Cody Gray - on strike Apr 21 '11 at 12:03
  • My point is that the splashscreen application does not have to reference any of the large DevComponents dlls mentioned in the original post. That and targeting a smaller .NET framework will make it faster. I have assumed that only the main application needs to reference (and hence load) all of the DevComponents dlls that seems to be making the original program load in 12 seconds or more. – Jason Moore Apr 21 '11 at 12:18
  • **1)** The DevComponents DLLs won't be loaded unless and until they are needed. If the splash screen form doesn't use them (and it shouldn't), then they won't get loaded just to display the splash screen. They'll only get loaded when the main form gets loaded, hopefully *after* the splash screen is up. **2)** The compact framework is for mobile devices, not desktop versions of Windows, so that's a non-starter. And version 4.0 is undeniably smaller than 2.0. Not sure about 1.0, but there's not much point to require *two* version of the FW to be installed with your app just for a splash screen. – Cody Gray - on strike Apr 21 '11 at 12:22