123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- namespace UniversalNetFrame451;
- using static Kernel32;
- using static Kernel32.DWORD;
- using HANDLE = IntPtr;
- public partial class Kernel32
- {
- internal enum DWORD : uint
- {
- CREATE_WAITABLE_TIMER_HIGH_RESOLUTION = 0x00000002,
- SYNCHRONIZE = 0x00100000,
- TIMER_MODIFY_STATE = 0x0002,
- INFINITE = 0xFFFFFFFF
- }
- [DllImport("kernel32.dll", EntryPoint = "GetSystemTimeAsFileTime")]
- internal static extern void GetSystemTimeAsFileTime(ref ulong lpSystemTimeAsFileTime);
- [DllImport("kernel32.dll", EntryPoint = "CreateWaitableTimerExW")]
- internal static extern HANDLE CreateWaitableTimerEx(IntPtr lpTimerAttributes, [In()][MarshalAs(UnmanagedType.LPWStr)] string lpTimerName, DWORD dwFlags, DWORD dwDesiredAccess);
- [DllImport("kernel32.dll", EntryPoint = "SetWaitableTimer")]
- [return: MarshalAs(UnmanagedType.Bool)]
- internal static extern bool SetWaitableTimer(HANDLE hTimer, ref long lpDueTime, int lPeriod, IntPtr pfnCompletionRoutine, IntPtr lpArgToCompletionRoutine, [MarshalAs(UnmanagedType.Bool)] bool fResume);
- [DllImport("kernel32.dll", EntryPoint = "CancelWaitableTimer")]
- [return: MarshalAs(UnmanagedType.Bool)]
- internal static extern bool CancelWaitableTimer(HANDLE hTimer);
- [DllImport("kernel32.dll", EntryPoint = "WaitForSingleObject")]
- internal static extern uint WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
- [DllImport("kernel32.dll", EntryPoint = "WaitForMultipleObjects")]
- internal static extern uint WaitForMultipleObjects(uint nCount, HANDLE[] lpHandles, int bWaitAll, DWORD dwMilliseconds);
- [DllImport("kernel32.dll", EntryPoint = "CloseHandle")]
- [return: MarshalAs(UnmanagedType.Bool)]
- internal static extern bool CloseHandle(HANDLE hObject);
- }
- public class SleepEx : IDisposable
- {
- HANDLE _hTimer = CreateWaitableTimerEx(IntPtr.Zero, null, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, SYNCHRONIZE | TIMER_MODIFY_STATE);
- private bool disposedValue;
- public bool Sleep(uint dwMilliseconds, WaitHandle breakHandle = null)
- {
- if (_hTimer == IntPtr.Zero)
- throw new NotSupportedException("CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is supported in Windows 10, version 1803, and later");
- long DueTime = -10 * 1000 * dwMilliseconds;
- SetWaitableTimer(_hTimer, ref DueTime, 0, IntPtr.Zero, IntPtr.Zero, false);
- if (breakHandle == null)
- return WaitForSingleObject(_hTimer, INFINITE) == 0;
- else
- return WaitForMultipleObjects(2, new nint[] { _hTimer, breakHandle.SafeWaitHandle.DangerousGetHandle() }, 0, INFINITE) == 0;
- }
- protected virtual void Dispose(bool disposing)
- {
- if (!disposedValue)
- {
- if (disposing)
- {
- // TODO: dispose managed state (managed objects)
- }
- // TODO: free unmanaged resources (unmanaged objects) and override finalizer
- // TODO: set large fields to null
- if (_hTimer != IntPtr.Zero)
- {
- CloseHandle(_hTimer);
- _hTimer = IntPtr.Zero;
- }
- disposedValue = true;
- }
- }
- // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
- ~SleepEx()
- {
- // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
- Dispose(disposing: false);
- }
- void IDisposable.Dispose()
- {
- // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
- Dispose(disposing: true);
- GC.SuppressFinalize(this);
- }
- }
- public class TimerEx : IDisposable
- {
- HANDLE _hTimer = IntPtr.Zero;
- private readonly CancellationTokenSource _cancellationTokenSource = new();
- private bool disposedValue;
- protected virtual void Dispose(bool disposing)
- {
- if (!disposedValue)
- {
- if (disposing)
- {
- // TODO: dispose managed state (managed objects)
- }
- // TODO: free unmanaged resources (unmanaged objects) and override finalizer
- // TODO: set large fields to null
- _cancellationTokenSource.Cancel();
- if (_hTimer != IntPtr.Zero)
- {
- CancelWaitableTimer(_hTimer);
- CloseHandle(_hTimer);
- _hTimer = IntPtr.Zero;
- }
- disposedValue = true;
- }
- }
- // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
- ~TimerEx()
- {
- // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
- Dispose(disposing: false);
- }
- public void Dispose()
- {
- // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
- Dispose(disposing: true);
- GC.SuppressFinalize(this);
- }
- public TimerEx(TimerCallback callback, object state, uint dueTime, uint period, uint times = uint.MaxValue)
- {
- ulong nowTime = 0;
- GetSystemTimeAsFileTime(ref nowTime);
- _hTimer = CreateWaitableTimerEx(IntPtr.Zero, null, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, SYNCHRONIZE | TIMER_MODIFY_STATE);
- if (_hTimer == IntPtr.Zero)
- throw new NotSupportedException("CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is supported in Windows 10, version 1803, and later");
- uint dueTimeMs = dueTime * 10000;
- uint periodMs = period * 10000;
- Task.Factory.StartNew(() =>
- {
- long DueTime = (long)nowTime + dueTimeMs;
- SetWaitableTimer(_hTimer, ref DueTime, 0, IntPtr.Zero, IntPtr.Zero, false);
- WaitForSingleObject(_hTimer, INFINITE);
- for (uint i = 1; i <= times && !_cancellationTokenSource.IsCancellationRequested; ++i)
- {
- callback?.Invoke(state);
- if (disposedValue)
- break;
- GetSystemTimeAsFileTime(ref nowTime);
- for (; DueTime < (long)nowTime;)
- DueTime += periodMs;
- SetWaitableTimer(_hTimer, ref DueTime, 0, IntPtr.Zero, IntPtr.Zero, false);
- WaitForSingleObject(_hTimer, INFINITE);
- }
- }, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
- }
- }
|