OSDN Git Service

FDK.カウンタ 名前空間を実装。
[strokestylet/CsWin10Desktop3.git] / FDK24 / カウンタ / 単純増加後反復カウンタ.cs
1 using System;
2 using System.Diagnostics;
3
4 namespace FDK.カウンタ
5 {
6         /// <summary>
7         /// ある int 型整数を、開始値から終了値まで、一定間隔で単純増加させるカウンタ。
8         /// 終了値に達したら開始値に戻る。以降、それを繰り返す。
9         /// </summary>
10         public class 単純増加後反復カウンタ
11         {
12                 /// <summary>
13                 /// カウンタを進行し、現在の値を取得する。
14                 /// </summary>
15                 public int 現在値
16                 {
17                         get
18                         {
19                                 lock( this.排他利用 )
20                                 {
21                                         this.進行する();
22                                         return this.bs_現在値;
23                                 }
24                         }
25                 }
26                 /// <summary>
27                 /// カウンタを進行し、現在の値を割合(0.0:開始値 ~ 1.0:終了値)に変換して取得する。
28                 /// </summary>
29                 public float 現在値の割合
30                 {
31                         get
32                         {
33                                 lock( this.排他利用 )
34                                 {
35                                         Debug.Assert( 0 != ( this.bs_終了値 - this.bs_開始値 ) );
36                                         this.進行する();
37                                         return (float) ( this.bs_現在値 - this.bs_開始値 ) / (float) ( this.bs_終了値 - this.bs_開始値 );
38                                 }
39                         }
40                 }
41                 public int 開始値
42                 {
43                         get
44                         {
45                                 lock( this.排他利用 )
46                                 {
47                                         return this.bs_開始値;
48                                 }
49                         }
50                 }
51                 public int 終了値
52                 {
53                         get
54                         {
55                                 lock( this.排他利用 )
56                                 {
57                                         return this.bs_終了値;
58                                 }
59                         }
60                 }
61                 /// <summary>
62                 /// カウンタを進行し、その結果、カウンタの進行がまだ動作中なら true を返す。(終了値に達しているかどうかは別問題。)
63                 /// </summary>
64                 public bool 動作中である
65                 {
66                         get
67                         {
68                                 lock( this.排他利用 )
69                                 {
70                                         this.進行する();    // 終了してるかどうか判定する前に、溜まってる進行を全部消化する。
71                                         return this.bs_動作中;
72                                 }
73                         }
74                 }
75                 /// <summary>
76                 /// カウンタの進行が一時停止されているなら true を返す。(終了値に達しているかどうかは別問題。)
77                 /// </summary>
78                 public bool 停止中である
79                         => !this.動作中である;
80
81                 /// <summary>
82                 /// コンストラクタ(1) 初期化のみ行い、カウンタは開始しない。
83                 /// </summary>
84                 public 単純増加後反復カウンタ()
85                 {
86                         this.間隔ms = QPCTimer.未使用;
87                         this.定間隔進行 = null;
88
89                         this.bs_開始値 = 0;
90                         this.bs_終了値 = 0;
91                         this.bs_現在値 = 0;
92                         this.bs_動作中 = false;
93                 }
94                 /// <summary>
95                 /// コンストラクタ(2) 初期化と同時にカウンタを開始する。
96                 /// </summary>
97                 public 単純増加後反復カウンタ( int 最初の値, int 最後の値, long 値をひとつ増加させるのにかける時間ms = 1000 ) : this()
98                 {
99                         this.開始する( 最初の値, 最後の値, 値をひとつ増加させるのにかける時間ms );
100                 }
101
102                 public void 開始する( int 最初の値, int 最後の値, long 値をひとつ増加させるのにかける時間ms = 1000 )
103                 {
104                         lock( this.排他利用 )
105                         {
106                                 this.間隔ms = 値をひとつ増加させるのにかける時間ms;
107                                 this.定間隔進行 = new 定間隔進行(); // 同時に開始する。
108                                 this.bs_開始値 = 最初の値;
109                                 this.bs_終了値 = System.Math.Max( 最初の値, 最後の値 );    // 逆転禁止。
110                                 this.bs_現在値 = 最初の値;
111                                 this.bs_動作中 = true;
112                         }
113                 }
114                 public void 一時停止する()
115                 {
116                         lock( this.排他利用 )
117                         {
118                                 this.定間隔進行.経過時間の計測を一時停止する();
119                                 this.bs_動作中 = false;
120                         }
121                 }
122                 public void 再開する()
123                 {
124                         lock( this.排他利用 )
125                         {
126                                 this.定間隔進行.経過時間の計測を再開する();
127                                 this.bs_動作中 = true;
128                         }
129                 }
130
131                 private long 間隔ms = QPCTimer.未使用;
132                 private 定間隔進行 定間隔進行 = null;
133                 private readonly object 排他利用 = new object();
134
135                 /// <summary>
136                 /// 前回のこのメソッドの呼び出しからの経過時間をもとに、必要なだけ現在値を増加させる。
137                 /// カウント値が終了値に達している場合は、開始値に繰り戻す。
138                 /// </summary>
139                 private void 進行する()
140                 {
141                         Debug.Assert( QPCTimer.未使用 != this.間隔ms );
142
143                         lock( this.排他利用 )
144                         {
145                                 this.定間隔進行?.経過時間の分だけ進行する( this.間隔ms, () => {
146
147                                         if( this.bs_動作中 )
148                                         {
149                                                 this.bs_現在値++;
150
151                                                 // 終了値を超えていれば開始値に戻る。
152                                                 if( this.bs_現在値 > this.bs_終了値 )
153                                                         this.bs_現在値 = this.bs_開始値;
154                                         }
155
156                                 } );
157                         }
158                 }
159
160                 #region " バックストア。"
161                 //---------------------------------
162                 private int bs_開始値 = 0;
163                 private int bs_終了値 = 0;
164                 private int bs_現在値 = 0;
165                 private bool bs_動作中 = false;
166                 //---------------------------------
167                 #endregion
168         }
169 }