From e18dd7b05fae992b41972bccdc21a89c05bfd44a Mon Sep 17 00:00:00 2001 From: Timothy Liu Date: Wed, 9 Mar 2022 19:26:09 +0800 Subject: [PATCH 1/9] doc(README): add method to get package --- README.md | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0243952..adb7cb3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# README +# FrameRateTask --- @@ -18,21 +18,31 @@ The source code of the dll is in the project FrameRateTask, and the example of u +## Get This Package + +To get this package, please enter nuget package page: [https://www.nuget.org/packages/FrameRateTask/](https://www.nuget.org/packages/FrameRateTask/) + +or use .NET CLI: + +```shell +$ dotnet add package FrameRateTask +``` + + + ## Author Autor: Timothy-LiuXuefeng -Job: Student at THU, major in EE +Job: Undergraduate in THU, major in EE -Copyright (C) 2021 Timothy Liu +Copyright (C) 2022 Timothy-LiuXuefeng ## LICENSE -MIT license - -Please check LICENSE.txt +[MIT license](./LICENSE.txt) From 801a2d0544f1360b5704504b96a3a632bb242727 Mon Sep 17 00:00:00 2001 From: Timothy Liu Date: Thu, 10 Mar 2022 10:58:09 +0800 Subject: [PATCH 2/9] chore(repo): add security policy --- SECURITY.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..3b6a820 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,7 @@ +# Security Policy + +## Reporting a Vulnerability + +Use this section to tell people how to report a vulnerability. + +**Please do not report security vulnerabilities through public GitHub issues.** Instead, please contact [liuxf19@163.com](liuxf19@163.com) to report them. From be53696e622356ae2ed28885e69b0c65cef4719a Mon Sep 17 00:00:00 2001 From: Timothy Liu Date: Thu, 10 Mar 2022 10:59:46 +0800 Subject: [PATCH 3/9] chore(bot): add renovate configuration --- renovate.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..200ab0a --- /dev/null +++ b/renovate.json @@ -0,0 +1,9 @@ +{ + "extends": [ + "config:base" + ], + "dependencyDashboard": true, + "timezone": "Asia/Shanghai", + "schedule": "after 4am and before 8am every saturday", + "labels": ["dependencies", "bot"] +} From 03d27e9d581f19b89906cd5d2e96cc89839dab5c Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 10 Mar 2022 03:03:51 +0000 Subject: [PATCH 4/9] chore(deps): update actions/setup-dotnet action to v2 --- .github/workflows/publish.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b58a061..0baa3d3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -11,7 +11,7 @@ jobs: - name: Fetch code uses: actions/checkout@v3 - name: Setup dotnet - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v2 with: dotnet-version: | 3.1.x diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 088e31e..daf29ff 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ jobs: - name: Fetch code uses: actions/checkout@v3 - name: Setup dotnet - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v2 with: dotnet-version: | 3.1.x From 2389252b26a39d5711b37639e293326c13ff19a4 Mon Sep 17 00:00:00 2001 From: Timothy Liu Date: Fri, 25 Mar 2022 14:30:21 +0800 Subject: [PATCH 5/9] chore: delete FramerateTask - Backup.csproj --- .../FrameRateTask - Backup.csproj | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100644 CSharp/FrameRateTask/FrameRateTask - Backup.csproj diff --git a/CSharp/FrameRateTask/FrameRateTask - Backup.csproj b/CSharp/FrameRateTask/FrameRateTask - Backup.csproj deleted file mode 100644 index 741b66d..0000000 --- a/CSharp/FrameRateTask/FrameRateTask - Backup.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - netcoreapp3.1;net5.0 - ../../LICENSE.txt - 1.0.0.0 - 1.0.0.0 - https://github.com/Timothy-LiuXuefeng/FrameRateTask - README.md - TimothyLiuXuefeng - $(Authors) - Copyright (C) 2022 - git - True - - - - .\FrameRateTask.xml - - - - .\FrameRateTask.xml - - - - - True - \ - - - - From 4be826732cf7df0529e35a4741552a6be1b6830d Mon Sep 17 00:00:00 2001 From: timothy Date: Fri, 25 Mar 2022 20:29:46 +0800 Subject: [PATCH 6/9] fix: data race when used in concurrent environment --- .github/workflows/test.yml | 5 +- CSharp/FrameRateTask/FrameRateTask.cs | 78 +++++++++++------ CSharp/Program.cs | 24 +++++ CSharp/Test/Program.cs | 38 ++++---- CSharp/TestConcurrency/Program.cs | 87 +++++++++++++++++++ CSharp/TestConcurrency/TestConcurrency.csproj | 14 +++ FrameRateTask.sln | 11 ++- README.md | 18 +--- 8 files changed, 211 insertions(+), 64 deletions(-) create mode 100644 CSharp/Program.cs create mode 100644 CSharp/TestConcurrency/Program.cs create mode 100644 CSharp/TestConcurrency/TestConcurrency.csproj diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index daf29ff..802b64f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,4 +22,7 @@ jobs: - name: Build FrameRateTask run: dotnet build "./CSharp/FrameRateTask/FrameRateTask.csproj" -c Release - name: Run test code - run: dotnet build "./CSharp/Test/Test.csproj" -c Release + run: | + dotnet build "./CSharp/Test/Test.csproj" -c Release + dotnet build "./CSharp/TestConcurrency/TestConcurrency.csproj" -c Release + dotnet run --project "./CSharp/TestConcurrency/TestConcurrency.csproj" -c Release diff --git a/CSharp/FrameRateTask/FrameRateTask.cs b/CSharp/FrameRateTask/FrameRateTask.cs index af66d07..bfca542 100644 --- a/CSharp/FrameRateTask/FrameRateTask.cs +++ b/CSharp/FrameRateTask/FrameRateTask.cs @@ -13,6 +13,7 @@ namespace Timothy.FrameRateTask { + /// /// The class intends to execute a task that need to be executed repeatedly every less than one second and need to be accurate. /// @@ -22,7 +23,12 @@ public class FrameRateTaskExecutor /// /// The actual framerate recently. /// - public uint FrameRate { get; private set; } + public uint FrameRate + { + get => (uint)Interlocked.CompareExchange(ref frameRate, 0, 0); + private set => Interlocked.Exchange(ref frameRate, value); + } + private long frameRate; /// /// Gets a value indicating whether or not the task has finished. @@ -30,7 +36,12 @@ public class FrameRateTaskExecutor /// /// true if the task has finished; otherwise, false. /// - public bool Finished { get; private set; } = false; + public bool Finished + { + get => Interlocked.CompareExchange(ref finished, 0, 0) != 0; + set => Interlocked.Exchange(ref finished, value ? 1 : 0); + } + private int finished = 0; /// /// Gets a value indicating whether or not the task has started. @@ -38,16 +49,15 @@ public class FrameRateTaskExecutor /// /// true if the task has started; otherwise, false. /// - public bool HasExecuted { get; private set; } = false; - private object hasExecutedLock = new object(); + public bool HasExecuted { get => Interlocked.CompareExchange(ref hasExecuted, 0, 0) != 0; } + private int hasExecuted = 0; private bool TrySetExecute() { - lock (hasExecutedLock) + if (Interlocked.Exchange(ref hasExecuted, 1) != 0) { - if (HasExecuted) return false; - HasExecuted = true; - return true; + return false; } + return true; } private TResult result; @@ -67,7 +77,6 @@ public TResult Result private set => result = value; } - /// /// Gets or sets whether it allows time exceeding. /// @@ -75,7 +84,15 @@ public TResult Result /// If this property is false, the task will throw a TimeExceed exception when the task cannot finish in the given time. /// The default value is true. /// - public bool AllowTimeExceed { get; set; } = true; + public bool AllowTimeExceed + { + get; +#if NET5_0_OR_GREATER + init; +#else + set; +#endif + } = true; /// /// It will be called once time exceeds if AllowTimeExceed is set true. @@ -83,17 +100,15 @@ public TResult Result /// /// 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. /// - public Action TimeExceedAction { get; set; } = callByExceed => { }; - - /// - /// The TickCount when beginning the loop, - /// - public long BeginTickCount { get; private set; } = 0L; - - /// - /// The TickCount should be when ending last loop. - /// - public long LastLoopEndingTickCount { get; private set; } + public Action TimeExceedAction + { + get; +#if NET5_0_OR_GREATER + init; +#else + set; +#endif + } = callByExceed => { }; /// /// Gets or sets the maximum count of time exceeding continuously. @@ -101,7 +116,15 @@ public TResult Result /// /// The value is 5 for default. /// - public ulong MaxTolerantTimeExceedCount { get; set; } = 5; + public ulong MaxTolerantTimeExceedCount + { + get; +#if NET5_0_OR_GREATER + init; +#else + set; +#endif + } = 5; /// /// Start this task synchronously. @@ -155,12 +178,13 @@ public FrameRateTaskExecutor loopFunc = () => { ulong timeExceedCount = 0UL; + long lastLoopEndingTickCount, beginTickCount; - var nextTime = (LastLoopEndingTickCount = BeginTickCount = Environment.TickCount64) + timeInterval; - var endTime = BeginTickCount < long.MaxValue - maxTotalDuration ? BeginTickCount + maxTotalDuration : long.MaxValue; + var nextTime = (lastLoopEndingTickCount = beginTickCount = Environment.TickCount64) + timeInterval; + var endTime = beginTickCount < long.MaxValue - maxTotalDuration ? beginTickCount + maxTotalDuration : long.MaxValue; uint loopCnt = 0; - var nextCntTime = BeginTickCount + 1000L; + var nextCntTime = beginTickCount + 1000L; while (loopCondition() && nextTime <= endTime) { @@ -191,7 +215,7 @@ public FrameRateTaskExecutor else if (AllowTimeExceed) TimeExceedAction(false); } - LastLoopEndingTickCount = nextTime; + lastLoopEndingTickCount = nextTime; nextTime += timeInterval; ++loopCnt; if (Environment.TickCount64 >= nextCntTime) @@ -203,9 +227,9 @@ public FrameRateTaskExecutor } result = finallyReturn(); + Interlocked.MemoryBarrierProcessWide(); Finished = true; }; - } /// diff --git a/CSharp/Program.cs b/CSharp/Program.cs new file mode 100644 index 0000000..d838d7a --- /dev/null +++ b/CSharp/Program.cs @@ -0,0 +1,24 @@ +// using Timothy.FrameRateTask; + + + +namespace TestNullable +{ + class Foo + { + public T val; + + public Foo(T val) + { + // this.val = val; + } + } + + static class Program + { + public static void Main() + { + + } + } +} diff --git a/CSharp/Test/Program.cs b/CSharp/Test/Program.cs index 4a14557..69363f4 100644 --- a/CSharp/Test/Program.cs +++ b/CSharp/Test/Program.cs @@ -11,7 +11,7 @@ static void Demo1() // The most common circumstance { Random r = new Random(); int cnt = 0; - FrameRateTaskExecutor frt = new FrameRateTaskExecutor + FrameRateTaskExecutor executor = new FrameRateTaskExecutor ( () => true, () => @@ -31,21 +31,21 @@ static void Demo1() // The most common circumstance ( () => { - while (!frt.Finished) + while (!executor.Finished) { - Console.WriteLine($"Now framerate: { frt.FrameRate }"); + Console.WriteLine($"Now framerate: { executor.FrameRate }"); Thread.Sleep(1000); } } ); - frt.Start(); + executor.Start(); } static void Demo2() // The most common circumstance. { int i = 1, sum = 0; Random r = new Random(); - FrameRateTaskExecutor frt = new FrameRateTaskExecutor + FrameRateTaskExecutor executor = new FrameRateTaskExecutor ( () => i <= 10, () => @@ -64,8 +64,8 @@ static void Demo2() // The most common circumstance. { MaxTolerantTimeExceedCount = ulong.MaxValue // Set it to ulong.MaxValue in case time exceeding could cause the result incorrect. }; - frt.Start(); - Console.WriteLine($"result: {frt.Result}"); + executor.Start(); + Console.WriteLine($"result: {executor.Result}"); } static void Demo3() { @@ -109,7 +109,7 @@ static void Demo4() { Random r = new Random(); int tm = 0; - FrameRateTaskExecutor frt = new FrameRateTaskExecutor + FrameRateTaskExecutor executor = new FrameRateTaskExecutor ( () => true, () => @@ -127,14 +127,14 @@ static void Demo4() ( () => { - while (!frt.Finished) + while (!executor.Finished) { - Console.WriteLine($"Now framerate: { frt.FrameRate }"); + Console.WriteLine($"Now framerate: { executor.FrameRate }"); Thread.Sleep(1000); } } ); - frt.Start(); + executor.Start(); } static void Demo5() @@ -143,7 +143,7 @@ static void Demo5() Random r = new Random(); int tm = 0; int cnt = 0; - FrameRateTaskExecutor frt = new FrameRateTaskExecutor + FrameRateTaskExecutor executor = new FrameRateTaskExecutor ( () => true, () => @@ -166,14 +166,14 @@ static void Demo5() ( () => { - while (!frt.Finished) + while (!executor.Finished) { - Console.WriteLine($"Now framerate: { frt.FrameRate }"); + Console.WriteLine($"Now framerate: { executor.FrameRate }"); Thread.Sleep(1000); } } ); - frt.Start(); + executor.Start(); } Console.WriteLine("You can see it is stable after it becomes clear."); @@ -185,7 +185,7 @@ static void Demo5() Random r = new Random(); int tm = 0; int cnt = 0; - FrameRateTaskExecutor frt = new FrameRateTaskExecutor + FrameRateTaskExecutor executor = new FrameRateTaskExecutor ( () => true, () => @@ -208,14 +208,14 @@ static void Demo5() ( () => { - while (!frt.Finished) + while (!executor.Finished) { - Console.WriteLine($"Now framerate: { frt.FrameRate }"); + Console.WriteLine($"Now framerate: { executor.FrameRate }"); Thread.Sleep(1000); } } ); - frt.Start(); + executor.Start(); Console.WriteLine("You can see it is NOT stable after it becomes clear."); } } diff --git a/CSharp/TestConcurrency/Program.cs b/CSharp/TestConcurrency/Program.cs new file mode 100644 index 0000000..7aac9af --- /dev/null +++ b/CSharp/TestConcurrency/Program.cs @@ -0,0 +1,87 @@ +using System; +using System.Threading; +using System.Diagnostics.CodeAnalysis; +using System.Collections.Concurrent; +using Timothy.FrameRateTask; + +namespace TestConcurrency +{ + internal class Program + { + static int Main(string[] args) + { + const int endVal = 2; + int cnt = 0; + var result = new BlockingCollection(); + var threadQueue = new BlockingCollection(); + + FrameRateTaskExecutor executor = new FrameRateTaskExecutor( + () => cnt < endVal, + () => + { + result.Add(cnt); + ++cnt; + }, + 1, + () => 8888 + ) + { AllowTimeExceed = true }; + + Action action = () => + { + for (int i = 0; i < 10; ++i) + { + var thrd = new Thread(() => + { + if (executor.TryStart()) + { + result.Add(executor.Result); + } + }); + threadQueue.Add(thrd); + thrd.Start(); + }; + }; + for (int i = 0; i < 20; ++i) + { + var thrd = new Thread(() => action()); + threadQueue.Add(thrd); + thrd.Start(); + } + + while (threadQueue.Count > 0) + { + threadQueue.TryTake(out Thread? thrd); + if (thrd is not null) + { + thrd.Join(); + } + } + for (int i = 0; i < endVal; ++i) + { + if (!result.TryTake(out int seq) || seq != i) + { + Console.WriteLine(); + if (result.Count > 0) + { + Console.Error.WriteLine($"Get error number: { seq }"); + } + else + { + Console.Error.WriteLine("Get no number!"); + } + return 1; + } + Console.Write(i.ToString() + ' '); + } + Console.WriteLine(); + if (!result.TryTake(out int res) || res != 8888) + { + Console.Error.WriteLine("Get error result!"); + return 1; + } + Console.WriteLine(res); + return 0; + } + } +} diff --git a/CSharp/TestConcurrency/TestConcurrency.csproj b/CSharp/TestConcurrency/TestConcurrency.csproj new file mode 100644 index 0000000..c5c118d --- /dev/null +++ b/CSharp/TestConcurrency/TestConcurrency.csproj @@ -0,0 +1,14 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + diff --git a/FrameRateTask.sln b/FrameRateTask.sln index 45441ca..d364adb 100644 --- a/FrameRateTask.sln +++ b/FrameRateTask.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31129.286 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32210.238 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{64E26841-2083-4D77-9238-20D5C3A1F993}" ProjectSection(SolutionItems) = preProject @@ -17,6 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "CSharp\Test\Test.cs EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CSharp", "CSharp", "{C0855812-2EBC-415D-92D3-C3B100DB3203}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestConcurrency", "CSharp\TestConcurrency\TestConcurrency.csproj", "{BD4BCC77-7900-46A2-A213-D4E3F611E53E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -31,6 +33,10 @@ Global {3B3B042E-7E86-4A93-B97F-FDF3A44D3722}.Debug|Any CPU.Build.0 = Debug|Any CPU {3B3B042E-7E86-4A93-B97F-FDF3A44D3722}.Release|Any CPU.ActiveCfg = Release|Any CPU {3B3B042E-7E86-4A93-B97F-FDF3A44D3722}.Release|Any CPU.Build.0 = Release|Any CPU + {BD4BCC77-7900-46A2-A213-D4E3F611E53E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BD4BCC77-7900-46A2-A213-D4E3F611E53E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BD4BCC77-7900-46A2-A213-D4E3F611E53E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BD4BCC77-7900-46A2-A213-D4E3F611E53E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -38,6 +44,7 @@ Global GlobalSection(NestedProjects) = preSolution {07261E94-73FD-43C5-AAAA-8C61E7576E47} = {C0855812-2EBC-415D-92D3-C3B100DB3203} {3B3B042E-7E86-4A93-B97F-FDF3A44D3722} = {C0855812-2EBC-415D-92D3-C3B100DB3203} + {BD4BCC77-7900-46A2-A213-D4E3F611E53E} = {C0855812-2EBC-415D-92D3-C3B100DB3203} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {19AB3133-5CDE-47FD-94A8-16088C24D599} diff --git a/README.md b/README.md index adb7cb3..080d9e2 100644 --- a/README.md +++ b/README.md @@ -93,31 +93,19 @@ Copyright (C) 2022 Timothy-LiuXuefeng > > 任务的返回值。如果任务未执行完毕,将会抛出异常。 -+ `public bool AllowTimeExceed { get; set; }` ++ `public bool AllowTimeExceed { get; init; }` > Whether the engine allow time exceeding. `true` fir default. Details are under `MaxTolerantTimeExceedCount`. > > 是否允许执行超时。默认为 `true`。详情参见 `MaxTolerantTimeExceedCount`。 -+ `public Action TimeExceedAction { get; set; }` ++ `public Action TimeExceedAction { get; init; }` > It will be called when time exceeds. Details are under `MaxTolerantTimeExceedCount`. > > 将在超时后被调用。详情参见 `MaxTolerantTimeExceedCount`。 -+ `public long BeginTickCount { get; }` - - > The tick count when beginning the loop. - > - > 循环开始时的 `TickCount` 值。 - -+ `public long LastLoopEndingTickCount { get; }` - - > The tick count when last loop ends. - > - > 上一次循环结束时的 `TickCount` 值。 - -+ `public ulong MaxTolerantTimeExceedCount { get; set; }` ++ `public ulong MaxTolerantTimeExceedCount { get; init; }` > The maximum number of time exceeding in a series. `5` for default. Once time exceeds, if the number of time exceeding in a series is no more than `MaxTolerantTimeExceedCount`, `TimeExceedAction` will be called with argument `false`, otherwise, if `AllowTimeExceed` is set `true`, `TimeExceedAction` will be called with argument `true`, otherwise (`AllowTimeExceed` is set `false`), it will throw an exception. > From b251b31dbdb52c26b39333901abb0b894399eb43 Mon Sep 17 00:00:00 2001 From: timothy Date: Sat, 26 Mar 2022 03:56:25 +0800 Subject: [PATCH 7/9] chore: update version to 1.1.0 --- CSharp/FrameRateTask/FrameRateTask.csproj | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CSharp/FrameRateTask/FrameRateTask.csproj b/CSharp/FrameRateTask/FrameRateTask.csproj index 2ea4f89..ffb44fc 100644 --- a/CSharp/FrameRateTask/FrameRateTask.csproj +++ b/CSharp/FrameRateTask/FrameRateTask.csproj @@ -2,8 +2,8 @@ netcoreapp3.1;net5.0;net6.0 - 1.0.0.0 - 1.0.0.0 + 1.1.0.0 + 1.1.0.0 https://github.com/Timothy-LiuXuefeng/FrameRateTask README.md TimothyLiuXuefeng @@ -13,6 +13,7 @@ True LICENSE.txt https://github.com/Timothy-LiuXuefeng/FrameRateTask + disable From f5c339be8554890cb8c1b06038ee9cd63d7dc801 Mon Sep 17 00:00:00 2001 From: timothy Date: Sat, 26 Mar 2022 04:18:24 +0800 Subject: [PATCH 8/9] chore: update package version to 1.1.0 --- CSharp/FrameRateTask/FrameRateTask.csproj | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CSharp/FrameRateTask/FrameRateTask.csproj b/CSharp/FrameRateTask/FrameRateTask.csproj index ffb44fc..7366361 100644 --- a/CSharp/FrameRateTask/FrameRateTask.csproj +++ b/CSharp/FrameRateTask/FrameRateTask.csproj @@ -4,6 +4,7 @@ netcoreapp3.1;net5.0;net6.0 1.1.0.0 1.1.0.0 + 1.1.0 https://github.com/Timothy-LiuXuefeng/FrameRateTask README.md TimothyLiuXuefeng @@ -24,6 +25,14 @@ .\FrameRateTask.xml + + 5 + + + + 5 + + True From 5911034afb599cb136f46850b5f99fa4559c6c87 Mon Sep 17 00:00:00 2001 From: timothy Date: Sat, 26 Mar 2022 04:20:03 +0800 Subject: [PATCH 9/9] chore: delete a unused file --- CSharp/Program.cs | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 CSharp/Program.cs diff --git a/CSharp/Program.cs b/CSharp/Program.cs deleted file mode 100644 index d838d7a..0000000 --- a/CSharp/Program.cs +++ /dev/null @@ -1,24 +0,0 @@ -// using Timothy.FrameRateTask; - - - -namespace TestNullable -{ - class Foo - { - public T val; - - public Foo(T val) - { - // this.val = val; - } - } - - static class Program - { - public static void Main() - { - - } - } -}