我想跟踪已加载的模块数量,以便用户可以看到剩余的加载量。所以我决定单独加载每个模块然后发布一个事件。
我可以看到订阅者正在点击并运行所有正确的代码,但UI不会更新,直到所有模块都已加载。所以我的进度条从0直到100。
所以要澄清一下,我遇到的问题是UI在整个模块加载过程中似乎都被冻结了。有什么方法可以利用进度条吗?
引导程序
{
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到显示进度条的shell
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;
}
}
答案 0 :(得分:1)
我最终确定了这一点。或者至少以我想要的方式工作。我刚刚使用Dispatcher并将其设置为后台优先级。
而不是
moduleManager.LoadModule(moduleInfo.ModuleName);
我用过
Application.Current.Dispatcher.Invoke(() => moduleManager.LoadModule(moduleInfo.ModuleName), DispatcherPriority.Background);
答案 1 :(得分:0)
我不认为我会使用EventAggregator
这样我认为我会使用带有“进度”窗口的常规事件来显示如下内容:
public sealed class ProgressEvent
{
public EventHandler AddModule;
private static ProgressEvent _instance = new ProgressEvent();
public static ProgressEvent GetInstance()
{
return _instance;
}
public void OnAddModule(object sender, EventArgs e)
{
var addModuleDelegate = AddModule as EventHandler;
if(addModuleDelegate != null)
{
addModuleDelegate.Invoke(sender, e);
}
}
}
并在模块内:
public void Initialize()
{
//do work here
ProgressEvent.GetInstance().OnAddModule(this, new EventArgs());
}
注册为:
public Progressbar()
{
InitializeComponent();
ProgressEvent.GetInstance().AddModule += AddProgress;
}
你肯定需要在单独的线程上加载。
列出Task.Run(()=> load modules);