Skip to content

Commit 8181eeb

Browse files
Merge pull request #27 from Timothy-LiuXuefeng/master
publish: stable version 1.1.0
2 parents 2772320 + 2e758ec commit 8181eeb

12 files changed

Lines changed: 233 additions & 106 deletions

File tree

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
- name: Fetch code
1212
uses: actions/checkout@v3
1313
- name: Setup dotnet
14-
uses: actions/setup-dotnet@v1
14+
uses: actions/setup-dotnet@v2
1515
with:
1616
dotnet-version: |
1717
3.1.x

.github/workflows/test.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
- name: Fetch code
1414
uses: actions/checkout@v3
1515
- name: Setup dotnet
16-
uses: actions/setup-dotnet@v1
16+
uses: actions/setup-dotnet@v2
1717
with:
1818
dotnet-version: |
1919
3.1.x
@@ -22,4 +22,7 @@ jobs:
2222
- name: Build FrameRateTask
2323
run: dotnet build "./CSharp/FrameRateTask/FrameRateTask.csproj" -c Release
2424
- name: Run test code
25-
run: dotnet build "./CSharp/Test/Test.csproj" -c Release
25+
run: |
26+
dotnet build "./CSharp/Test/Test.csproj" -c Release
27+
dotnet build "./CSharp/TestConcurrency/TestConcurrency.csproj" -c Release
28+
dotnet run --project "./CSharp/TestConcurrency/TestConcurrency.csproj" -c Release

CSharp/FrameRateTask/FrameRateTask - Backup.csproj

Lines changed: 0 additions & 32 deletions
This file was deleted.

CSharp/FrameRateTask/FrameRateTask.cs

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace 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>

CSharp/FrameRateTask/FrameRateTask.csproj

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
<PropertyGroup>
44
<TargetFrameworks>netcoreapp3.1;net5.0;net6.0</TargetFrameworks>
5-
<FileVersion>1.0.0.0</FileVersion>
6-
<AssemblyVersion>1.0.0.0</AssemblyVersion>
5+
<FileVersion>1.1.0.0</FileVersion>
6+
<AssemblyVersion>1.1.0.0</AssemblyVersion>
7+
<VersionPrefix>1.1.0</VersionPrefix>
78
<RepositoryUrl>https://github.com/Timothy-LiuXuefeng/FrameRateTask</RepositoryUrl>
89
<PackageReadmeFile>README.md</PackageReadmeFile>
910
<Authors>TimothyLiuXuefeng</Authors>
@@ -13,6 +14,7 @@
1314
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
1415
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
1516
<PackageProjectUrl>https://github.com/Timothy-LiuXuefeng/FrameRateTask</PackageProjectUrl>
17+
<Nullable>disable</Nullable>
1618
</PropertyGroup>
1719

1820
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@@ -23,6 +25,14 @@
2325
<DocumentationFile>.\FrameRateTask.xml</DocumentationFile>
2426
</PropertyGroup>
2527

28+
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net6.0|AnyCPU'">
29+
<WarningLevel>5</WarningLevel>
30+
</PropertyGroup>
31+
32+
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0|AnyCPU'">
33+
<WarningLevel>5</WarningLevel>
34+
</PropertyGroup>
35+
2636
<ItemGroup>
2737
<None Include="..\..\README.md">
2838
<Pack>True</Pack>

CSharp/Test/Program.cs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ static void Demo1() // The most common circumstance
1111
{
1212
Random r = new Random();
1313
int cnt = 0;
14-
FrameRateTaskExecutor<int> frt = new FrameRateTaskExecutor<int>
14+
FrameRateTaskExecutor<int> executor = new FrameRateTaskExecutor<int>
1515
(
1616
() => true,
1717
() =>
@@ -31,21 +31,21 @@ static void Demo1() // The most common circumstance
3131
(
3232
() =>
3333
{
34-
while (!frt.Finished)
34+
while (!executor.Finished)
3535
{
36-
Console.WriteLine($"Now framerate: { frt.FrameRate }");
36+
Console.WriteLine($"Now framerate: { executor.FrameRate }");
3737
Thread.Sleep(1000);
3838
}
3939
}
4040
);
41-
frt.Start();
41+
executor.Start();
4242
}
4343

4444
static void Demo2() // The most common circumstance.
4545
{
4646
int i = 1, sum = 0;
4747
Random r = new Random();
48-
FrameRateTaskExecutor<int> frt = new FrameRateTaskExecutor<int>
48+
FrameRateTaskExecutor<int> executor = new FrameRateTaskExecutor<int>
4949
(
5050
() => i <= 10,
5151
() =>
@@ -64,8 +64,8 @@ static void Demo2() // The most common circumstance.
6464
{
6565
MaxTolerantTimeExceedCount = ulong.MaxValue // Set it to ulong.MaxValue in case time exceeding could cause the result incorrect.
6666
};
67-
frt.Start();
68-
Console.WriteLine($"result: {frt.Result}");
67+
executor.Start();
68+
Console.WriteLine($"result: {executor.Result}");
6969
}
7070
static void Demo3()
7171
{
@@ -109,7 +109,7 @@ static void Demo4()
109109
{
110110
Random r = new Random();
111111
int tm = 0;
112-
FrameRateTaskExecutor<int> frt = new FrameRateTaskExecutor<int>
112+
FrameRateTaskExecutor<int> executor = new FrameRateTaskExecutor<int>
113113
(
114114
() => true,
115115
() =>
@@ -127,14 +127,14 @@ static void Demo4()
127127
(
128128
() =>
129129
{
130-
while (!frt.Finished)
130+
while (!executor.Finished)
131131
{
132-
Console.WriteLine($"Now framerate: { frt.FrameRate }");
132+
Console.WriteLine($"Now framerate: { executor.FrameRate }");
133133
Thread.Sleep(1000);
134134
}
135135
}
136136
);
137-
frt.Start();
137+
executor.Start();
138138
}
139139

140140
static void Demo5()
@@ -143,7 +143,7 @@ static void Demo5()
143143
Random r = new Random();
144144
int tm = 0;
145145
int cnt = 0;
146-
FrameRateTaskExecutor<int> frt = new FrameRateTaskExecutor<int>
146+
FrameRateTaskExecutor<int> executor = new FrameRateTaskExecutor<int>
147147
(
148148
() => true,
149149
() =>
@@ -166,14 +166,14 @@ static void Demo5()
166166
(
167167
() =>
168168
{
169-
while (!frt.Finished)
169+
while (!executor.Finished)
170170
{
171-
Console.WriteLine($"Now framerate: { frt.FrameRate }");
171+
Console.WriteLine($"Now framerate: { executor.FrameRate }");
172172
Thread.Sleep(1000);
173173
}
174174
}
175175
);
176-
frt.Start();
176+
executor.Start();
177177
}
178178
Console.WriteLine("You can see it is stable after it becomes clear.");
179179

@@ -185,7 +185,7 @@ static void Demo5()
185185
Random r = new Random();
186186
int tm = 0;
187187
int cnt = 0;
188-
FrameRateTaskExecutor<int> frt = new FrameRateTaskExecutor<int>
188+
FrameRateTaskExecutor<int> executor = new FrameRateTaskExecutor<int>
189189
(
190190
() => true,
191191
() =>
@@ -208,14 +208,14 @@ static void Demo5()
208208
(
209209
() =>
210210
{
211-
while (!frt.Finished)
211+
while (!executor.Finished)
212212
{
213-
Console.WriteLine($"Now framerate: { frt.FrameRate }");
213+
Console.WriteLine($"Now framerate: { executor.FrameRate }");
214214
Thread.Sleep(1000);
215215
}
216216
}
217217
);
218-
frt.Start();
218+
executor.Start();
219219
Console.WriteLine("You can see it is NOT stable after it becomes clear.");
220220
}
221221
}

0 commit comments

Comments
 (0)