Initial commit

This commit is contained in:
2026-07-03 16:31:37 +07:00
commit 899c7c637d
1939 changed files with 641750 additions and 0 deletions

View File

@@ -0,0 +1,157 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace RobotNet10.RobotApp.Services.Robot;
internal static partial class Windows
{
[LibraryImport("winmm.dll")]
internal static partial uint timeBeginPeriod(uint uPeriod);
[LibraryImport("winmm.dll")]
internal static partial uint timeEndPeriod(uint uPeriod);
}
public static class HighPrecisionTimerHelper
{
public static void EnableHighPrecision()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
_ = Windows.timeBeginPeriod(2);
}
}
public static void DisableHighPrecision()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
_ = Windows.timeEndPeriod(2);
}
}
}
public class HighPrecisionTimer<T>(int Interval, Action Callback, Logger<T>? Logger) : IDisposable where T : class
{
public bool Disposed;
private Thread? Thread;
private long IntervalTicks;
private long NextDueTime;
private readonly Lock Lock = new();
private void Handler()
{
while (!Disposed)
{
long now = Stopwatch.GetTimestamp();
bool shouldRun = false;
lock (Lock)
{
if (Disposed) break;
if (now >= NextDueTime)
{
shouldRun = true;
long scheduledTime = NextDueTime;
NextDueTime += IntervalTicks;
// Tự đồng bộ nếu lệch quá
long driftTicks = now - scheduledTime;
if (driftTicks > IntervalTicks / 2)
{
Logger?.Warning($"High-res timer drift: {driftTicks * 1000.0 / Stopwatch.Frequency:F3}ms. Resync.");
NextDueTime = now + IntervalTicks;
}
}
}
// === BƯỚC 2: Chạy callback ===
if (shouldRun)
{
try
{
Callback.Invoke();
}
catch (Exception ex)
{
Logger?.Error($"Callback error in high-precision timer: {ex}");
}
}
// === BƯỚC 3: Chờ chính xác đến lần sau ===
long sleepUntil = NextDueTime;
while (!Disposed)
{
now = Stopwatch.GetTimestamp();
long remaining = sleepUntil - now;
if (remaining <= 0)
break;
// > 1ms → Sleep
if (remaining > Stopwatch.Frequency / 1000)
{
Thread.Sleep(1);
}
// < 1ms → SpinWait
else
{
Thread.SpinWait((int)(remaining / 10));
}
}
}
}
public void Start()
{
if (!Disposed)
{
lock (Lock)
{
if (Interval < 30) HighPrecisionTimerHelper.EnableHighPrecision();
IntervalTicks = (long)(Interval * (Stopwatch.Frequency / 1000.0));
Thread = new Thread(Handler) { IsBackground = true, Priority = ThreadPriority.Highest };
NextDueTime = Stopwatch.GetTimestamp() + IntervalTicks;
Thread.Start();
}
}
else throw new ObjectDisposedException(nameof(HighPrecisionTimer<T>));
}
public void Stop()
{
if (Disposed) return;
if (Thread != null)
{
Disposed = true;
lock (Lock)
{
Thread.Join(100);
Thread = null;
HighPrecisionTimerHelper.DisableHighPrecision();
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (Disposed) return;
if (disposing) Stop();
Disposed = true;
}
~HighPrecisionTimer()
{
Dispose(false);
}
}