マーキーラベルの実装である以下のコードがあります。マーキーラベルを、さまざまなコンピューター間で一定の速度を維持しながら、コンピューター上で可能な限り最も効率的な速度で実行したいと思います。プログラムが実行されているコンピューターを最大限に活用できるように、スキップされる「フレーム」の量を最小限に抑えたいと思います。しかし同時に、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;
}
}
}