Thread.sleep代码(1);对于Silverlight动画来说太慢了,还有其他选择吗?

时间:2009-07-21 18:06:26

标签: c# silverlight

我有这个算法在动画中的Canvas上绘制了很多像素。但是我无法控制动画的速度并且绘制得非常快,所以我添加了一个Thread.Sleep(1)但是当绘制几千个像素时它太慢了。 我尝试过一个故事板方法,但结果却非常缓慢。

那么还有Thread.sleep的替代方案可以减慢我的循环吗?

void DrawGasket(object sender, DoWorkEventArgs e)
    {
        Random rnd = new Random();
        Color color = Colors.White;
        while (Counter <= noOfPx)
        {
            switch (rnd.Next(3))
            {
                case 0:
                    m_lastPoint.X = (m_top.X + m_lastPoint.X)/2;
                    m_lastPoint.Y = (m_top.Y + m_lastPoint.Y)/2;
                    color = Colors.White;
                    break;
                case 1:
                    m_lastPoint.X = (m_left.X + m_lastPoint.X)/2;
                    m_lastPoint.Y = (m_left.Y + m_lastPoint.Y)/2;
                    color = Colors.Orange;
                    break;
                case 2:
                    m_lastPoint.X = (m_right.X + m_lastPoint.X)/2;
                    m_lastPoint.Y = (m_right.Y + m_lastPoint.Y)/2;
                    color = Colors.Purple;
                    break;
            }
            Dispatcher.BeginInvoke(() =>
            {
                var px = new Rectangle { 
                                       Height = m_pxSize, 
                                       Width = m_pxSize,
                                       Fill = new SolidColorBrush(color) 
                                       };
                Canvas.SetTop(px, m_lastPoint.Y);
                Canvas.SetLeft(px, m_lastPoint.X);
                can.Children.Add(px);
                lblCounter.Text = Counter.ToString();
            });
            Counter++;
            Thread.Sleep(1);
        }
    }

5 个答案:

答案 0 :(得分:13)

难道你不能只通过循环每次迭代而不是每次迭代都会睡觉吗?

答案 1 :(得分:4)

这是一个简单的方法:您希望它在特定时间绘制...在每个循环期间让它看看它是什么时间。如果是“时间”(无论如何)你确定的比率,那么绘制/更新。否则,只需循环。 (例如,如果您希望每秒更新10次,并且刚刚更新了,那么将当前时间存储在变量中......然后与该变量进行比较。直到它变为十分之一秒,不要重绘,只是循环。)

这还不错,只要你能在这个循环中做任何你需要做的事情。但是,如果这个循环必须完成,那么在发生任何其他事情之前,你只需要等待很多cpu循环。

如果你想获得幻想,并且这样做,你可以让它看到已经过了多少时间,然后以正确的数量更新视觉效果。因此,例如,如果你希望你的对象每秒移动30个像素,你可以只更新精确的位置,(例如,如果.0047秒已经过去,它应该移动.141像素)。您存储该值。当然,从视觉上看,直到循环的另一轮,它才会移动,但确切地说它移动的时间和 time 确定的距离,而不是计算机的速度。通过这种方式,无论机器的速度如何,您都可以每秒移动30个像素......它只会在慢速机器上跳线。

答案 2 :(得分:4)

每次Silverlight绘制框架时都会触发CompositionTarget.Rendering事件,这是编写任何自定义绘图代码的好地方。您可以使用其他一些机制(如计时器)来跟踪“游戏时间”,并在绘图代码的单独线程(或至少单独的执行路径)上适当调整模型。这样,当绘制UI时,没有计算可执行,您只需绘制模型的当前状态。基本上只需将Dispatcher.BeginInvoke中的代码移动到CompositionTarget.Rendering的事件处理程序中,我相信你会很好。

答案 3 :(得分:3)

一种选择是每次不睡觉:

if(Counter % 2 == 0) Thread.Sleep(1);

答案 4 :(得分:3)

无论有没有Thread.Sleep(),渲染速度取决于系统的速度,或者进程获得的时间。 - &GT;糟糕!

你应该使用现在编写视频游戏的方法。跟踪当前时间,并且每秒只调用BeginInvoke()x次(其中x是每秒帧数渲染速度)

在BeginInvoked功能中,检查绘制了多少以及还需要绘制多少。特别是每个Rectangle都没有BeginInvoke。即使没有Thread.Sleep(),它也始终是一个上下文切换。