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._開始値;
}
} );
}
}
}
}