0

マーキーラベルの実装である以下のコードがあります。マーキーラベルを、さまざまなコンピューター間で一定の速度を維持しながら、コンピューター上で可能な限り最も効率的な速度で実行したいと思います。プログラムが実行されているコンピューターを最大限に活用できるように、スキップされる「フレーム」の量を最小限に抑えたいと思います。しかし同時に、CPUを100%消費する必要はありません(これらのステートメントは矛盾していますか?わかりません)。

現在、アニメーションループの反復ごとに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;
        }
    }
}
4

0 に答える 0