C# EventWaitHandle。舞台调度。在C语言中设置唤醒计时器#
但是,将创建新线程:C# EventWaitHandle。舞台调度。在C语言中设置唤醒计时器#,c#,multithreading,delegates,C#,Multithreading,Delegates,但是,将创建新线程: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.ComponentModel;
using System.Windows.Forms;
using System.Diagnostics;
class WakeUp
{
[DllImport("kernel32.dll")]
public static extern SafeWaitHandle CreateWaitableTimer(IntPtr lpTimerAttributes, bool bManualReset, string lpTimerName);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWaitableTimer(SafeWaitHandle hTimer, [In] ref long pDueTime, int lPeriod, IntPtr pfnCompletionRoutine, IntPtr lpArgToCompletionRoutine, bool fResume);
//tmParam will be converted to the proper data type inside
//the class. Just send DateTime with the correct WakeUp time
//As the only param to the constructor of WakeUp
public WakeUp(DateTime tmParam)
{
//Create a new thread to set the waitable timer
//setWaitable(tmParam);
Debug.Print("Starting thread...");
Thread t = new Thread( () => setWaitable(tmParam) );
t.Start();
}
static void setWaitable(DateTime smParam)
{
long waketime = smParam.ToFileTime();
using (SafeWaitHandle handle = CreateWaitableTimer(IntPtr.Zero, true, DateTime.Now.ToString()))
{
//I need to try starting this block in a new thread since there is some blocking going on
//to set the waitable timer
if (SetWaitableTimer(handle, ref waketime, 0, IntPtr.Zero, IntPtr.Zero, true))
{
using (EventWaitHandle wh = new EventWaitHandle(false, EventResetMode.AutoReset))
{
wh.SafeWaitHandle = handle;
wh.WaitOne();
Debug.Print("TimerSet "+smParam.ToString());
}
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
}
}
从不打印到输出窗口。可以将构造函数更改为:
Debug.Print("TimerSet "+smParam.ToString());
但是,这将阻止当前线程,该线程需要大约两分钟或更短的时间,但每次都有效。我想把事情转到它自己的轨道上来
出于某种原因,我在创建新线程EventWaitHandle时发布的第一种方式似乎永远不会回来。我想这只是永远的阻碍。这可能是线程之间的安全问题吗
我只是想澄清一下,我打电话是这样的:
public WakeUp(DateTime tmParam)
{
//Create a new thread to set the waitable timer
//setWaitable(tmParam);
Debug.Print("Starting thread...");
setWaitable(tmParam);
}
谢谢你
WakeUp test1 = new wakeUp(DateTime.Now.AddMinutes(2));
SetWaitableTimer()的pDueTime参数可以是增量的,也可以是绝对的。通过传递负值来指定增量值。但是你用的是正值,所以你得到的是绝对时间。显然,如果你使用增量价值,你会领先,因为这才是你真正想要的。使用TimeSpan.Ticks属性
使用绝对时间是可以的,但是当你在罗马时,你必须像个罗马人一样行事,操作系统的时钟以UTC运行。当地时间只适用于人类。从SetWaitableTimer的MSDN文章:
计时器状态设置为信号状态后的时间,间隔为100纳秒。使用FILETIME结构描述的格式。正值表示绝对时间确保使用基于UTC的绝对时间,因为系统在内部使用基于UTC的时间。负值表示相对时间。实际的计时器精度取决于硬件的性能。有关基于UTC的时间的更多信息,请参阅系统时间
您必须使用DateTime.UtcNow
SetWaitableTimer()的pDueTime参数可以是增量的,也可以是绝对的。通过传递负值来指定增量值。但是你用的是正值,所以你得到的是绝对时间。显然,如果你使用增量价值,你会领先,因为这才是你真正想要的。使用TimeSpan.Ticks属性
使用绝对时间是可以的,但是当你在罗马时,你必须像个罗马人一样行事,操作系统的时钟以UTC运行。当地时间只适用于人类。从SetWaitableTimer的MSDN文章:
计时器状态设置为信号状态后的时间,间隔为100纳秒。使用FILETIME结构描述的格式。正值表示绝对时间确保使用基于UTC的绝对时间,因为系统在内部使用基于UTC的时间。负值表示相对时间。实际的计时器精度取决于硬件的性能。有关基于UTC的时间的更多信息,请参阅系统时间
您必须使用
DateTime.UtcNow
为什么要为计时器创建新线程?计时器的全部要点是,创建计时器对象,它会异步通知您(通过在单独的线程上调用回调函数)。当计时器周期已过时。在这方面,WaitableTimer
与.NET timer对象System.Threading.timer
没有什么不同。在WaitableTimer
的情况下,您可以让它发出事件信号,这很方便
几年前,我写了一篇关于使用C#的WaitableTimer
的文章。不幸的是,承载这篇文章的网站已经不存在了。代码和示例可从中获得
您可能想查看,它显示了计时器的典型使用方式。WaitableTimer的机制略有不同,但概念相同。为什么要为计时器创建新线程?计时器的全部要点是,创建计时器对象,它会异步通知您(通过在单独的线程上调用回调函数)。当计时器周期已过时。在这方面,
WaitableTimer
与.NET timer对象System.Threading.timer
没有什么不同。在WaitableTimer
的情况下,您可以让它发出事件信号,这很方便
几年前,我写了一篇关于使用C#的WaitableTimer
的文章。不幸的是,承载这篇文章的网站已经不存在了。代码和示例可从中获得
您可能想查看,它显示了计时器的典型使用方式。WaitableTimer的机制稍有不同,但概念相同
new wakeUp(DateTime.Now.AddMinutes(2)