棱镜事件聚合器。加载模块时发布事件

Prism EventAggregator. Publishing event while loading modules

我想跟踪已加载模块的总数,以便用户可以看到剩余的加载量。所以我决定单独加载每个模块,然后发布一个事件。

我可以看到订阅者被击中并且 运行 通过所有正确的代码,但是 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;
    }
}

我不认为我会为此使用 EventAggregator 我认为我会使用带有进度 window 的常规事件来显示如下内容:

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);

我确实弄明白了。或者至少按照我想要的方式工作。我刚刚使用了 Dispatcher 并将其设置为后台优先级。

而不是

moduleManager.LoadModule(moduleInfo.ModuleName);

我用过

Application.Current.Dispatcher.Invoke(() => moduleManager.LoadModule(moduleInfo.ModuleName), DispatcherPriority.Background);