1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.ComponentModel;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        class WakeUp
        {

            public static SafeWaitHandle[] tSafeWaitHandles = new SafeWaitHandle[6];
            public static WaitHandle[][] waitHandles = new WaitHandle[6][];

            bool rslt;

            //Various imports of kernel32.dll so the waitable timer can be set
            //on the system
            [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);

            [DllImport("kernel32.dll", SetLastError = true)]
            public static extern bool CancelWaitableTimer(SafeWaitHandle hTimer);

            //SafeHandle.DangerousGetHandle Method
            [DllImport("kernel32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool CloseHandle(IntPtr hObject);

            //The constructor will use a TimeSpan to set a waitable timer
            public WakeUp(string wtName, int alarmNum)
            {
                tSafeWaitHandles[alarmNum] = CreateWaitableTimer(IntPtr.Zero, true, wtName);
            }

            public int initWakeUp(TimeSpan smParam, int alarmNum)
            {
                //The number of ticks needs to be negated to set a waitable timer in this fashion
                long waketicks = -smParam.Ticks;
                rslt = SetWaitableTimer(tSafeWaitHandles[alarmNum], ref waketicks, 0, IntPtr.Zero, IntPtr.Zero, true);
                return Convert.ToInt32(rslt);
            }

            public int DoWork(int alarmNum)
            {
                waitHandles[0] = new WaitHandle[] 
                {
                    new AutoResetEvent(false),
                    new AutoResetEvent(false)
                };


                waitHandles[alarmNum][0].SafeWaitHandle = tSafeWaitHandles[alarmNum];

                WaitHandle.WaitAny(waitHandles[alarmNum]);

                Thread.Sleep(5000);


                return 0;
            }

        } 

        static void Main(string[] args)
        {
            Console.WriteLine( DateTime.Now );

            WakeUp temp = new WakeUp("spalarm1", 0);
            temp.initWakeUp(TimeSpan.FromMinutes(1), 0);
            temp.DoWork(0);

            //I would like an optional Set which will cause DoWork to stop blocking
            //when set is called. Is this possible to do?
            //WakeUp.waitHandles[0][1].Set();

            Console.WriteLine(DateTime.Now);
            Console.WriteLine("Done...");
            Console.ReadKey();
        }
    }
}

程序设置一个等待定时器。那部分工作正常。线程一直阻塞,直到定时器触发。我想做的是能够在其中一个 WaitHandles 上调用 .Set 以释放线程阻塞。似乎这段代码的编写方式 .Set 不可用,所以我现在已经注释掉了该行。我需要能够调用其中一个计时器以释放线程阻塞。有谁知道如何做到这一点?

我现在遇到的问题是我对 set 的调用以:

错误 1“System.Threading.WaitHandle”不包含“Set”的定义,并且找不到接受“System.Threading.WaitHandle”类型的第一个参数的扩展方法“Set”(您是否缺少 using 指令或程序集参考?) C:\Users\Eric\Documents\Visual Studio 2013\Projects\waitany\ConsoleApplication1\Program.cs 86 38 ConsoleApplication1

4

1 回答 1

1

Set方法是在(and 的基类)中声明的,EventWaitHandle而不是在. 由于该类将s 公开为 的数组,因此您不能直接调用它们。无论如何,更简洁的方法是在类中添加一个特定的方法来设置等待句柄;公开暴露它们会破坏封装。AutoResetEventManualResetEventWaitHandleWakeUpAutoResetEventWaitHandlesSetWakeUp

于 2014-07-01T00:16:07.033 回答