如何在 STA 线程上与引导程序同时运行动画 SplashScreen

Posted

技术标签:

【中文标题】如何在 STA 线程上与引导程序同时运行动画 SplashScreen【英文标题】:How to run an animated SplashScreen at the same time as a Bootstrapper on STA threads 【发布时间】:2013-07-25 12:47:52 【问题描述】:

背景:

我正在开发一个 WPF 应用程序,该应用程序使用 MEF 框架自动链接应用程序所需的库和组件。随着人们添加自己的组件,在较慢的机器上加载需要 0-2 秒到 6-7 秒。为此,我认为需要一个漂亮的启动画面来让用户知道应用程序正在加载。理想情况下,初始屏幕会显示动画进度条以及描述正在加载哪些组件的状态文本字段。

问题:

我设计了一个在应用程序启动时调用的初始屏幕窗口 (OnStartup),然后加载 MEF 引导程序。问题当然是,窗口没有动画,因为它与 MEF 引导程序加载在同一个线程上。我尝试将引导程序放在单独的线程上,但它抱怨它不是 STA 线程。即使在 STA 线程上,它仍然不喜欢它,并且在尝试加载主应用程序窗口时抛出错误。 我不能将初始屏幕窗口本身放在单独的线程上,因为我无法访问它,而且它必须是一个 STA 线程,因为它也是一个 UI 组件。(意识到这一点是不真实的,我可以和线程交谈)

更新

我找到了一个解决方案,我将启动屏幕窗口保存在单独的 STA 线程中。感谢所有回复的人指出我正确的方向:

    protected override void OnStartup(StartupEventArgs e)
    
        base.OnStartup(e);

        Dispatcher threadDispacher = null;
        Thread thread = new Thread((ThreadStart)delegate
        
            threadDispacher = Dispatcher.CurrentDispatcher;
            SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(threadDispacher));

            loadingWindow = new LoadingWindow();
            loadingWindow.Closed += (s, ev) => threadDispacher.BeginInvokeShutdown(DispatcherPriority.Background);
            loadingWindow.Show();

            System.Windows.Threading.Dispatcher.Run();
        );

        thread.SetApartmentState(ApartmentState.STA);
        thread.IsBackground = true;
        thread.Start();

        var bootstrapper = new Bootstrapper();
        bootstrapper.Run();

        if (threadDispacher != null)
        
            threadDispacher.BeginInvoke(new Action(delegate  loadingWindow.Close(); ));
        
    

【问题讨论】:

如果它在一个单独的线程上,你为什么不能访问它?您应该仍然可以引用它,您只需要保护您的 UI 访问并使用 Dispatcher 将调用编组到窗口的 UI 线程。 如果用户选择关闭初始屏幕,这将不起作用。应用程序不会退出。 【参考方案1】:

您将引导程序移动到自己的线程中是正确的。 但是,您应该做的是确保需要在 UI 线程上执行的部分也在 UI 线程上调用

因此,当 MEF 引导程序完成后,您可以在主线程上调用隐藏启动窗口和打开主窗口,甚至可以从 MEF 的线程调用。

通过dispatcher 将消息传递到主线程的一种方法

【讨论】:

以上是关于如何在 STA 线程上与引导程序同时运行动画 SplashScreen的主要内容,如果未能解决你的问题,请参考以下文章

#yyds干货盘点# 醒酒菜:动画图解核心内存区--堆

任务 - 如何确保 ContinueWith 操作是 STA 线程?

如何将消息发布到运行消息泵的 STA 线程?

如何在 iOS 7 上与设备旋转一起制作动画

为什么Task.Delay打破了线程的STA状态?

如何使用引导程序更改导航栏中的过渡动画?