如何在创建用户控件时显示动画

时间:2011-01-26 13:20:26

标签: c# .net wpf performance animation

在WPF 4应用程序中,我有一个非常大的用户控件,充满了控件,需要4s才能在快速机器上初始化。在此期间,申请当然根本没有回应 在初始化此控件时,有没有办法在主窗口中显示动画?

我知道我不能在另一个线程上创建它。但是,是否有一种方法可以从Dispatcher中以较低的优先级创建它,以便我可以在主窗口上显示一个旋转的轮子,它仍会旋转?

(我现在能想到的唯一解决方案就是将用户控制分解为更多部分并仅在需要时加载它们。但这需要花费大量的开发时间来进行更改。)

UPDATE1
更清楚:它是一个使用标签页的简单WPF窗口。打开新标签页时,我正在初始化用户控件,该控件保存此标签页的控件。其中一个用户控件是如此充满控件,需要4秒才会显示新的标签页 所以我认为展示一个旋转轮比阻塞应用程序更好。

3 个答案:

答案 0 :(得分:5)

我认为你将不得不将这个用户控件分解成碎片。您可以使用BackgroundWorker来协调此用户控件的“构建”。每次触发DoWork事件时,使用Dispatcher.BeginInvoke创建向UI添加下一个控件。以下博客文章中描述了此技术:

http://loekvandenouweland.com/index.php/2010/12/wp7-add-user-controls-graphics-in-background-thread/

这将允许您在加载过程中显示动画。

答案 1 :(得分:2)

为什么不能在另一个线程上初始化它?我看到两种情况:

  1. 在进入核心WPF初始化之前,在另一个线程上预加载/预先计算的非WPF原因的初始化很慢。
  2. WPF本身消耗4秒的CPU时间(但是,这实际上是WTF级别的CPU时间......)。如果是这样,你可以用它自己的消息泵启动另一个STA线程,它可以显示一个独立的UI(例如:一个旋转轮),直到主线程完成加载。
  3. 您可以创建“对话框”,隐式创建新的Dispatcher并在后台线程上运行,或者您可以显式创建自己的Dispatcher(=消息泵)。

    我使用以下方法:

    public static Dispatcher StartNewDispatcher(ThreadPriority cpuPriority = ThreadPriority.Normal) {
        using (var sem = new SemaphoreSlim(0)) {
            Dispatcher retval = null;
            var winThread = new Thread(() => {
                retval = Dispatcher.CurrentDispatcher;
                sem.Release();
                Dispatcher.Run();
            }) { IsBackground = true, Priority = cpuPriority };
            winThread.SetApartmentState(ApartmentState.STA);
            winThread.Start();
            sem.Wait();
            return retval;
        }
    }
    

    这为您提供了真正的多线程UI;但它也意味着你不能数据绑定或以任何其他方式直接在两个UI之间进行通信:毕竟,WPF对象具有线程关联性。

    在你走这条路线之前,确认你没有任何慢速组件可以使用探查器预加载:选项1(在WPF初始化之前预加载重物)更简单,更清洁。

答案 2 :(得分:0)

解决方案可能是将慢速部分(不属于控件的数据?)移动到另一个线程,如上所述。

或使用VirtualizingStackPanel延迟加载所需的内容。

你能详细说明推迟的原因吗?