I'd like to keep track of the number of modules that have been loaded over the total so the user can see how much loading is left. So I've decided to load each module individually and then publish an event.
I can see that the Subscriber is getting hit and running through all the correct code, but the UI wont update until all modules have been loaded. So my progress bar just goes from 0 straight to 100.
So to clarify, the problem I have is that the UI appears to be frozen throughout the entire module loading process. Is there any way around this so I can utilize a progress bar?
Bootstrapper
{
protected override void InitializeModules()
{
FillModuleCatalogFromConfig();
// begin the initialization process
eventAggregator = this.Container.Resolve<IEventAggregator>();
eventAggregator.GetEvent<BeginLoadingModulesEvent>().Publish(true);
// load the rest of the modules
InitializeRemainingModules();
eventAggregator.GetEvent<BeginLoadingModulesEvent>().Publish(false);
}
private void InitializeRemainingModules()
{
foreach (var module in ModuleCatalog.Modules)
{
InitializeModule(module);
}
}
private void InitializeModule(ModuleInfo moduleInfo)
{
if (moduleInfo.State == ModuleState.Initialized)
return;
if (moduleInfo.DependsOn.Count > 0)
{
// Load any dependencies first
foreach (var dependenciesModulesName in moduleInfo.DependsOn)
{
// if the dependency isn't loaded then we'll have to load that first
ModuleInfo module = ModuleCatalog.Modules.First(x => x.ModuleName == dependenciesModulesName);
if (module.State != ModuleState.Initialized)
{
// must initialize this module first
InitializeModule(module);
}
}
}
eventAggregator.GetEvent<MyEvent>().Publish(new ProgressChangedEventArgs(CalculateModulesLoadedProgress(), moduleInfo.ModuleName));
moduleManager.LoadModule(moduleInfo.ModuleName);
}
private int CalculateModulesLoadedProgress()
{
decimal progress = Decimal.Divide(ModuleCatalog.Modules.Where(x => x.State == ModuleState.Initialized).Count(), ModuleCatalog.Modules.Count()) * 100;
return (int)(Math.Round(progress));
}
}
ViewModel to the shell that displays the progress bar
public Class ShellViewModel
{
IEventAggregator ea;
ShellViewModel(IEventAggregator ea)
{
this.ea = ea;
this.ea.GetEvent<MyEvent>().Subscribe(this.UpdateProgressBar);
}
public int ProgressValue
{
get { return progressValue; }
set { SetProperty(ref progressValue, value); }
}
private void UpdateProgressBar(ProgressChangedEventArgs args)
{
// this all gets hit and runs fine, but the actual UI bar for progress
// wont get hit until all modules are done loading
this.ProgressValue = args.ProgressPercentage;
}
}
I did end up figuring this out. Or at least getting working the way I wanted it to. I just used the Dispatcher and set it to a background priority.
Instead of
moduleManager.LoadModule(moduleInfo.ModuleName);
I used
Application.Current.Dispatcher.Invoke(() => moduleManager.LoadModule(moduleInfo.ModuleName), DispatcherPriority.Background);