2014-06-30 7 views
0
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을 사용할 수 없어서 지금 당장 그 행을 주석 처리했습니다. 스레드를 차단하지 못하도록 타이머 중 하나를 호출 할 수 있어야합니다. 누구든지이 작업을 수행하는 방법을 알고 있습니까?WaitAny()가있는 WaitHandles 배열 사용

내가 지금 가지고있는 문제와 끝 설정 내 전화입니다 :

오류 1 'System.Threading.WaitHandle' '설정'에 대한 정의 및 승인없이 확장 메서드 '설정'을 포함하지 않는 'System.Threading.WaitHandle'형식의 첫 번째 인수를 찾을 수 있습니다 (사용 지시문이나 어셈블리 참조가 누락 되었습니까?) C : \ Users \ Eric \ Documents \ Visual Studio 2013 \ Projects \ waitany \ ConsoleApplication1 \ Program.cs 86 38 콘솔 응용 프로그램 1

답변

1

메서드는 EventWaitHandle (기본 클래스는 AutoResetEventManualResetEvent)가 아니라 WaitHandle입니다. WakeUp 클래스는 AutoResetEventWaitHandles의 배열로 나타 내기 때문에 Set을 직접 호출 할 수 없습니다. 어쨌든, 더 깨끗한 접근법은 대기 핸들을 설정하기 위해 WakeUp 클래스에 특정 메소드를 추가하는 것입니다. 캡슐화를 공개적으로 중단합니다.