C# 睡眠(1);对于Silverlight动画来说太慢了,有其他选择吗?

C# 睡眠(1);对于Silverlight动画来说太慢了,有其他选择吗?,c#,silverlight,C#,Silverlight,我有一个算法,在动画中在画布上画很多像素。但是我无法控制动画的速度,而且它的绘制速度非常快,所以我添加了一个线程。Sleep(1)但是当绘制几千像素时,它太慢了。 我尝试过故事板的方法,但结果是速度非常慢 那么有没有其他方法可以代替Thread.sleep来减慢我的循环 void DrawGasket(object sender, DoWorkEventArgs e) { Random rnd = new Random(); Color color = C

我有一个算法,在动画中在画布上画很多像素。但是我无法控制动画的速度,而且它的绘制速度非常快,所以我添加了一个线程。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);
        }
    }
void Draw垫圈(对象发送器,DoWorkEventArgs e)
{
随机rnd=新随机();
颜色=颜色。白色;
while(柜台)
{
var px=新矩形{
高度=m_px尺寸,
宽度=m_px尺寸,
填充=新的SolidColorBrush(颜色)
};
Canvas.SetTop(px,m_lastPoint.Y);
Canvas.SetLeft(px,m_lastPoint.X);
can.Children.Add(px);
lblCounter.Text=Counter.ToString();
});
计数器++;
睡眠(1);
}
}

难道你不能在循环中每N次迭代而不是每次迭代都休眠一次吗?

这里有一个简单的方法:你想让它在一个特定的时间绘制……在每个循环中,让它看看它是什么时间。如果您确定的是“时间”(无论什么)速率,则绘制/更新。否则,只需循环。(例如,如果您希望每秒更新10次,而您刚刚更新,则将当前时间存储在一个变量中…然后与该变量进行比较。直到10秒后,才重新绘制,只需循环。)

这还不错,只要你能在这个循环中做任何你需要做的事情。然而,如果这个循环必须在其他任何事情发生之前完成,那么在等待的过程中就会消耗大量的cpu周期


如果你想变得更花哨,并且做得很好,你可以让它看看经过了多少时间,然后用正确的数量更新视觉效果。例如,如果你想让你的对象每秒移动30个像素,你可以只更新它的精确位置(例如,如果.0047秒过去了,它应该移动.141个像素)。您存储该值。当然,从视觉上看,它在下一轮循环之前根本不会移动,但它移动的确切时间和距离将取决于时间,而不是计算机的速度。这样,无论机器的速度如何,它都会以每秒30像素的速度移动……在速度较慢的机器上,它只会跳得更厉害。

一个选择是每次都不要睡觉:


if(计数器%2==0)线程睡眠(1)

无论是否使用Thread.Sleep(),渲染速度取决于系统的速度或进程的时间。->糟糕

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


在BeginInvoked函数中,检查已绘制多少以及仍需要绘制多少。特别是不要为每一个长方形开始思考。即使没有Thread.Sleep(),它也始终是一个上下文开关。

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

我有点喜欢时间的想法,尽管它可能有点复杂,但它允许循环在不同的计算机上以大致相同的速度运行;它在速度快的电脑上比在速度慢的+1电脑上睡眠的频率更高,因为这意味着(本质上)一个计时循环。还有其他选项(例如,在内存中绘制和仅在需要显示新图像时翻转图像),但这直接解决了问题。我稍后将尝试实现这一点,因为这是制作动画的更好方法。但现在我要用mattnewport的解决方案。