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)