在非托管的Win32环境中,我习惯于使用CreateWaitableTimer API创建的等待计时器,可用于同步调用,例如WaitForSingleObject,主要用于WaitForMultipleObjects。
在.NET和C#中必须有一个模拟可等待的计时器?
答案 0 :(得分:6)
你需要什么样的等待计时器?
我可以等待'的默认课程。在.NET中是System.Threading.Tasks.Task
。在.NET 4.5中,您只需使用Task.Delay(milliseconds)
。
在.NET 4.0中,您可以使用TaskCompletionSource
创建任务,并使用普通计时器将其设置为已完成。或者使用Async Targeting Pack或AsyncBridge
TaskEx.Delay
实施
如果您需要实际WaitHandle
,可以使用ManualResetEvent
,并使用普通的.NET计时器来设置事件。
或者,您可以创建自己的类,该类派生自WaitHandle
和P / Invoke CreateWaitableTimer
。
似乎这样的类已经存在于.NET框架中,但它是内部的。 (来自System.ServiceModel.Internals.dll
的{{3}})
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();
}
}
}