如何改进这个C#动画代码

时间:2013-02-09 15:42:28

标签: c# animation sleep

我有下面的代码,它是一个marquee标签的实现。我希望marquee标签能够在计算机上以最有效的速度运行,同时在不同的计算机上保持恒定的速度。我希望跳过的“帧”数量最小化,以便程序充分利用它运行的计算机。但与此同时,我不一定要消耗100%的CPU(这些陈述是否矛盾?我不确定)。

目前我正在为动画循环的每次迭代睡10毫秒。这对我来说是浪费,似乎它可能会减慢可能需要额外10毫秒的较慢计算机上的动画速度。我不确定在睡眠方法中使用的最佳价值是什么,或者即使我应该睡觉。我读过一些关于Sleep(0)和Sleep(1)以及Yield和SpinWait的内容,但我无法理解这一切。

将Invalidate调用太多也是一件坏事吗?我可以通过调用它来超载吗?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.Diagnostics;
using Timer = System.Timers.Timer;
using System.Threading;

namespace Scoreboard
{
    public class MarqueeLabel : Label
    {
        private float _marqueeOffset;
        private float _marqueeMeasurement;

        public MarqueeLabel()
        {
            UseCompatibleTextRendering = true;

            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.UserPaint, true);

            Thread t = new Thread(ThreadRun);
            t.IsBackground = true;
            t.Start();
        }

        public void ThreadRun()
        {
            long time = DateTime.Now.Ticks;
            long diff = 0;

            while (true)
            {
                float step = -((float)diff / (20 * TimeSpan.TicksPerMillisecond)); //change "frame" based on the elapsed time
                _marqueeOffset = _marqueeOffset >= -_marqueeMeasurement ? _marqueeOffset + step : Width;

                Invalidate();
                Thread.Sleep(10); // how long should i wait here?

                long temp = DateTime.Now.Ticks;
                diff = temp - time;
                time = temp;
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            StringFormat stringFormat = new StringFormat();
            stringFormat.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap;
            stringFormat.Trimming = StringTrimming.None;
            stringFormat.Alignment = StringAlignment.Near;

            Rectangle rect = ClientRectangle;
            rect.X += (int)_marqueeOffset;
            e.Graphics.DrawString(Text, Font, new SolidBrush(ForeColor), rect, stringFormat);
        }

        protected override void OnTextChanged(EventArgs e)
        {
            base.OnTextChanged(e);
            MeasureText();
        }

        protected override void OnFontChanged(EventArgs e)
        {
            base.OnFontChanged(e);
            MeasureText();
        }

        void MeasureText()
        {
            _marqueeMeasurement = CreateGraphics().MeasureString(Text, Font).Width;
        }
    }
}

0 个答案:

没有答案