1313
1414namespace Timothy . FrameRateTask
1515{
16+
1617 /// <summary>
1718 /// The class intends to execute a task that need to be executed repeatedly every less than one second and need to be accurate.
1819 /// </summary>
@@ -22,32 +23,41 @@ public class FrameRateTaskExecutor<TResult>
2223 /// <summary>
2324 /// The actual framerate recently.
2425 /// </summary>
25- public uint FrameRate { get ; private set ; }
26+ public uint FrameRate
27+ {
28+ get => ( uint ) Interlocked . CompareExchange ( ref frameRate , 0 , 0 ) ;
29+ private set => Interlocked . Exchange ( ref frameRate , value ) ;
30+ }
31+ private long frameRate ;
2632
2733 /// <summary>
2834 /// Gets a value indicating whether or not the task has finished.
2935 /// </summary>
3036 /// <returns>
3137 /// true if the task has finished; otherwise, false.
3238 /// </returns>
33- public bool Finished { get ; private set ; } = false ;
39+ public bool Finished
40+ {
41+ get => Interlocked . CompareExchange ( ref finished , 0 , 0 ) != 0 ;
42+ set => Interlocked . Exchange ( ref finished , value ? 1 : 0 ) ;
43+ }
44+ private int finished = 0 ;
3445
3546 /// <summary>
3647 /// Gets a value indicating whether or not the task has started.
3748 /// </summary>
3849 /// <returns>
3950 /// true if the task has started; otherwise, false.
4051 /// </returns>
41- public bool HasExecuted { get ; private set ; } = false ;
42- private object hasExecutedLock = new object ( ) ;
52+ public bool HasExecuted { get => Interlocked . CompareExchange ( ref hasExecuted , 0 , 0 ) != 0 ; }
53+ private int hasExecuted = 0 ;
4354 private bool TrySetExecute ( )
4455 {
45- lock ( hasExecutedLock )
56+ if ( Interlocked . Exchange ( ref hasExecuted , 1 ) != 0 )
4657 {
47- if ( HasExecuted ) return false ;
48- HasExecuted = true ;
49- return true ;
58+ return false ;
5059 }
60+ return true ;
5161 }
5262
5363 private TResult result ;
@@ -67,41 +77,54 @@ public TResult Result
6777 private set => result = value ;
6878 }
6979
70-
7180 /// <summary>
7281 /// Gets or sets whether it allows time exceeding.
7382 /// </summary>
7483 /// <remarks>
7584 /// If this property is false, the task will throw a TimeExceed exception when the task cannot finish in the given time.
7685 /// The default value is true.
7786 /// </remarks>
78- public bool AllowTimeExceed { get ; set ; } = true ;
87+ public bool AllowTimeExceed
88+ {
89+ get ;
90+ #if NET5_0_OR_GREATER
91+ init;
92+ #else
93+ set;
94+ #endif
95+ } = true ;
7996
8097 /// <summary>
8198 /// It will be called once time exceeds if AllowTimeExceed is set true.
8299 /// </summary>
83100 /// <remarks>
84101 /// parameter bool: If it is called because of the number of time exceeding is greater than MaxTimeExceedCount, the argument is true; if it is called because of exceeding once, the argument is false.
85102 /// </remarks>
86- public Action < bool > TimeExceedAction { get ; set ; } = callByExceed => { } ;
87-
88- /// <summary>
89- /// The TickCount when beginning the loop,
90- /// </summary>
91- public long BeginTickCount { get ; private set ; } = 0L ;
92-
93- /// <summary>
94- /// The TickCount should be when ending last loop.
95- /// </summary>
96- public long LastLoopEndingTickCount { get ; private set ; }
103+ public Action < bool > TimeExceedAction
104+ {
105+ get ;
106+ #if NET5_0_OR_GREATER
107+ init;
108+ #else
109+ set;
110+ #endif
111+ } = callByExceed => { } ;
97112
98113 /// <summary>
99114 /// Gets or sets the maximum count of time exceeding continuously.
100115 /// </summary>
101116 /// <remarks>
102117 /// The value is 5 for default.
103118 /// </remarks>
104- public ulong MaxTolerantTimeExceedCount { get ; set ; } = 5 ;
119+ public ulong MaxTolerantTimeExceedCount
120+ {
121+ get ;
122+ #if NET5_0_OR_GREATER
123+ init;
124+ #else
125+ set;
126+ #endif
127+ } = 5 ;
105128
106129 /// <summary>
107130 /// Start this task synchronously.
@@ -155,12 +178,13 @@ public FrameRateTaskExecutor
155178 loopFunc = ( ) =>
156179 {
157180 ulong timeExceedCount = 0UL ;
181+ long lastLoopEndingTickCount , beginTickCount ;
158182
159- var nextTime = ( LastLoopEndingTickCount = BeginTickCount = Environment . TickCount64 ) + timeInterval ;
160- var endTime = BeginTickCount < long . MaxValue - maxTotalDuration ? BeginTickCount + maxTotalDuration : long . MaxValue ;
183+ var nextTime = ( lastLoopEndingTickCount = beginTickCount = Environment . TickCount64 ) + timeInterval ;
184+ var endTime = beginTickCount < long . MaxValue - maxTotalDuration ? beginTickCount + maxTotalDuration : long . MaxValue ;
161185
162186 uint loopCnt = 0 ;
163- var nextCntTime = BeginTickCount + 1000L ;
187+ var nextCntTime = beginTickCount + 1000L ;
164188
165189 while ( loopCondition ( ) && nextTime <= endTime )
166190 {
@@ -191,7 +215,7 @@ public FrameRateTaskExecutor
191215 else if ( AllowTimeExceed ) TimeExceedAction ( false ) ;
192216 }
193217
194- LastLoopEndingTickCount = nextTime ;
218+ lastLoopEndingTickCount = nextTime ;
195219 nextTime += timeInterval ;
196220 ++ loopCnt ;
197221 if ( Environment . TickCount64 >= nextCntTime )
@@ -203,9 +227,9 @@ public FrameRateTaskExecutor
203227 }
204228
205229 result = finallyReturn ( ) ;
230+ Interlocked . MemoryBarrierProcessWide ( ) ;
206231 Finished = true ;
207232 } ;
208-
209233 }
210234
211235 /// <summary>
0 commit comments