在非托管 Win32 世界中,我习惯于使用CreateWaitableTimer API 创建的可等待计时器,这些计时器可用于同步调用,例如WaitForSingleObject,主要用于WaitForMultipleObjects。
.NET 和 C# 中必须有一个可等待计时器的模拟?
在非托管 Win32 世界中,我习惯于使用CreateWaitableTimer API 创建的可等待计时器,这些计时器可用于同步调用,例如WaitForSingleObject,主要用于WaitForMultipleObjects。
.NET 和 C# 中必须有一个可等待计时器的模拟?
你需要等待计时器做什么?
.NET 中“我可以等待的东西”的默认类是System.Threading.Tasks.Task
. 在 .NET 4.5 中,您可以简单地使用Task.Delay(milliseconds)
.
在 .NET 4.0 中,您可以使用 aTaskCompletionSource
创建任务,并使用普通计时器将其设置为已完成。或者使用Async Targeting Pack或AsyncBridgeTaskEx.Delay
中的实现
如果您需要实际的WaitHandle
,您可以使用ManualResetEvent
, 并使用普通的 .NET 计时器来设置事件。
或者,您可以创建自己的派生自WaitHandle
P/Invoke的类CreateWaitableTimer
。.NET 框架中似乎已经存在这样的类,但它是内部的。(System.Runtime.IOThreadTimer.WaitableTimer
来自System.ServiceModel.Internals.dll
)
public class WaitableTimer : WaitHandle
{
[DllImport("kernel32.dll")]
static extern SafeWaitHandle CreateWaitableTimer(IntPtr lpTimerAttributes, bool bManualReset, string lpTimerName);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetWaitableTimer(SafeWaitHandle hTimer, [In] ref long pDueTime, int lPeriod, IntPtr pfnCompletionRoutine, IntPtr lpArgToCompletionRoutine, [MarshalAs(UnmanagedType.Bool)] bool fResume);
public WaitableTimer(bool manualReset = true, string timerName = null)
{
this.SafeWaitHandle = CreateWaitableTimer(IntPtr.Zero, manualReset, timerName);
}
public void Set(long dueTime)
{
if (!SetWaitableTimer(this.SafeWaitHandle, ref dueTime, 0, IntPtr.Zero, IntPtr.Zero, false))
{
throw new Win32Exception();
}
}
}