using System; using System.Diagnostics; namespace FDK.カウンタ { /// /// ある int 型整数を、開始値から終了値まで、一定間隔で単純増加させるカウンタ。 /// 終了値に達したら開始値に戻る。以降、それを繰り返す。 /// public class 単純増加後反復カウンタ { /// /// カウンタを進行し、現在の値を取得する。 /// public int 現在値 { get { lock( this._スレッド間同期 ) { this._進行する(); return this._現在値; } } } /// /// カウンタを進行し、現在の値を割合(0.0:開始値 ~ 1.0:終了値)に変換して取得する。 /// public float 現在値の割合 { get { lock( this._スレッド間同期 ) { Debug.Assert( 0 != ( this._終了値 - this._開始値 ) ); this._進行する(); return (float) ( this._現在値 - this._開始値 ) / (float) ( this._終了値 - this._開始値 ); } } } public int 開始値 { get { lock( this._スレッド間同期 ) { return this._開始値; } } } public int 終了値 { get { lock( this._スレッド間同期 ) { return this._終了値; } } } /// /// カウンタを進行し、その結果、カウンタの進行がまだ動作中なら true を返す。 /// (終了値に達しているかどうかは別問題。) /// public bool 動作中である { get { lock( this._スレッド間同期 ) { this._進行する(); // 終了してるかどうか判定する前に、溜まってる進行を全部消化する。 return this._動作中; } } } /// /// カウンタの進行が一時停止されているなら true を返す。 /// (終了値に達しているかどうかは別問題。) /// public bool 停止中である => !this.動作中である; /// /// 初期化のみ行い、カウンタは開始しない。 /// public 単純増加後反復カウンタ() { this._間隔ms = QPCTimer.未使用; this._定間隔進行 = null; this._開始値 = 0; this._終了値 = 0; this._現在値 = 0; this._動作中 = false; } /// /// 初期化し、同時にカウンタを開始する。 /// public 単純増加後反復カウンタ( int 最初の値, int 最後の値, long 値をひとつ増加させるのにかける時間ms = 1000 ) : this() { this.開始する( 最初の値, 最後の値, 値をひとつ増加させるのにかける時間ms ); } public void 開始する( int 最初の値, int 最後の値, long 値をひとつ増加させるのにかける時間ms = 1000 ) { lock( this._スレッド間同期 ) { this._間隔ms = 値をひとつ増加させるのにかける時間ms; this._定間隔進行 = new 定間隔進行(); // 同時に開始する。 this._開始値 = 最初の値; this._終了値 = System.Math.Max( 最初の値, 最後の値 ); // 逆転しないことを保証。 this._現在値 = 最初の値; this._動作中 = true; } } public void 一時停止する() { lock( this._スレッド間同期 ) { this._定間隔進行.経過時間の計測を一時停止する(); this._動作中 = false; } } public void 再開する() { lock( this._スレッド間同期 ) { this._定間隔進行.経過時間の計測を再開する(); this._動作中 = true; } } private int _開始値 = 0; private int _終了値 = 0; private int _現在値 = 0; private bool _動作中 = false; private long _間隔ms = QPCTimer.未使用; private 定間隔進行 _定間隔進行 = null; private readonly object _スレッド間同期 = new object(); /// /// 前回のこのメソッドの呼び出しからの経過時間をもとに、必要なだけ現在値を増加させる。 /// カウント値が終了値に達している場合は、開始値に繰り戻す。 /// private void _進行する() { if( this._間隔ms == QPCTimer.未使用 ) return; // 開始されていないなら無視。 lock( this._スレッド間同期 ) { this._定間隔進行?.経過時間の分だけ進行する( this._間隔ms, () => { if( this._動作中 ) { this._現在値++; // 終了値を超えていれば開始値に戻る。 if( this._現在値 > this._終了値 ) this._現在値 = this._開始値; } } ); } } } }