Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I report progress on loading assemblies into the Current AppDomain in .Net on a splash screen?

I'm having a little difficulty in displaying the progress of assemblies being loaded into the AppDomain.CurrentDomain.

What I want to do is display a splash screen that has a progress bar, I want to be able to update this Progress bar as each assembly is loaded into memory in the AppDomain. This way users will have a visual indicator as to the progress of the application launch.

I don't care that assemblies are loaded before the Splash Screen is rendered which is actually just a standard WPF Window with a progress bar. Once a Splash Screen is loaded I would like to report the assemblies as they are loaded. I am not manually loading these Assemblies.

So far I have handled the Startup event in App.xaml with the following markup:

Startup="Application_Startup"

The corresponding code behind for startup is as follows:

private void Application_Startup(object sender, StartupEventArgs e)
{
SplashScreen.Show<SplashScreen>();
AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad;
}

void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
    SplashScreen.CallSplashScreenMethod<SplashScreen>(x => x.Text(args.LoadedAssembly.GetName().Name));
}

This works as I expect it, a splash screen is displayed and whatever assemblies are being loaded at the moment the splash screen is displayed are showed on screen without a problem.

splashscreen

The problem here is that I can't see a way of reporting progress of assemblies being loaded.

Assemblies don't seem to be loaded linearly in any particular order, due to this I am not sure how to go about getting a count of the remaining number of assemblies to be loaded. I can't see an obvious way to get what assemblies are currently being loaded.

If I could get a list of assemblies yet to be loaded by the CLR I could implement a progress bar by using either a standard count, along the lines

progress = numberOfLoadedAssemblies / totalNumberOfAssemblies * 100;

Or by implementing the logic from Chris Marisic's excellent answer on using a weighted average

I can't do a trivial "Directory.GetFiles().Length" To get the total number of assemblies to be loaded. The reason why is because the CLR isn't loading assemblies in any particular order. It seems to load some assemblies from the application root, then some from the GAC, then more from the application root.

What I'd like to know is if there is a way to get a list of remaining assemblies to be loaded.

like image 224
Daniel Lane Avatar asked Oct 20 '22 02:10

Daniel Lane


1 Answers

As others have stated you can't just assume 9 assemblies out of 10 loaded means 90%. However you can make these assumptions alot more realistic.

Scan the file info of all of the assemblies that will be loaded so you have the filesize of each assembly. Now create a weighted value for the "average" assembly.

var totalSize =  assemblies.Select(x=> x.FileSize).Sum();
var averageSize = totalSize / assemblies.Count();

var averageChange = averageSize / totalSize;

Assuming your progress bar is a scale of 0 to 1, you could just add averageChange each time another assembly is loaded.

Or you could actually count the bytes loaded vs the total size for the progress bar. I personally would go with my averaged method to prevent the progress bar going from [--] to [-------------------] from a single assembly. Users are not accustomed to non-linear changes and are not prone to trust non-linear changes. Giving them a linearly increasing progress bar that ends almost exactly when it's done loading gives people the proper feelings of things are working and will be done soon. Erratic jumps in progress bars will make the users feel the system is erratic and untrustworthy.

One thing I cannot understate is how easy it is to anger your users with a progress bar. Nothing angers users more than a progress bar that rapidly fills hits 99% and halts. It makes them feel like the program froze. They also need visual indication that between any meter that things have not frozen. They also don't want to sit around for a long time (this is seconds mind you) see a progress bar fill and then flip back to zero.

like image 79
Chris Marisic Avatar answered Oct 31 '22 18:10

Chris Marisic