2

私は、コンピューターをスリープ状態から復帰させて何らかの作業を行うことができる、たとえば C# で 30 分の定期的なタイマーを作成しようとしています。

ウェブで調べた結果、Waitableタイマー機能を使用する必要があるようです。テストコードをいくつか作成しましたが、期待どおりに動作しません。タイマーを作成することは可能であり、コードをデバッグしてステップ実行しているときにコールバックが数回呼び出されます。しかし、ブレークポイントなしでコードを実行すると、コールバックは数回しか呼び出されません。

ボタンを押すと「testWaitableTimer」を実行するフォームアプリケーションを作成しました。「myTimerEvent」は、各タイマーイベントの時間を出力することになっています。テスト時に30分のタイムアウトを待ちたくないので、期間は2秒間隔に設定され、期限は5秒です。

    public void myTimerEvent(IntPtr complretionArg, UInt32 timerLow, UInt32 timerHigh)
    {
       SetText( DateTime.Now.ToString() + "hepp ");
    }

    public delegate void TimerCompleteDelegate(IntPtr complretionArg,
                                           UInt32 timerLow, UInt32 timerHigh);

    [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, TimerCompleteDelegate pfnCompletionRoutine, IntPtr lpArgToCompletionRoutine, bool fResume);

    SafeWaitHandle handle;
    private void testWaitableTimer()
    {

        DateTime utc = DateTime.Now.AddSeconds(5);
        long duetime = utc.ToFileTime();

        using (handle = CreateWaitableTimer(IntPtr.Zero, true, "MyWaitabletimer"))
        {
            // create a periodic timer that will fire of the first event after 5sec and then every 2 sec
            if (SetWaitableTimer(handle, ref duetime, 2000, myTimerEvent, IntPtr.Zero, true))
            {
                using (EventWaitHandle wh = new EventWaitHandle(false, EventResetMode.AutoReset))
                {
                    wh.SafeWaitHandle = handle;
                    wh.WaitOne();                       // wait for first event
                    System.Threading.Thread.Sleep(2000);
                    wh.WaitOne();                       // wait for second event
                    System.Threading.Thread.Sleep(500);
                    wh.WaitOne();                       // wait for third event.

                }
            }
            else
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }
        }
    }

私はC#にかなり慣れていないので、いくつか質問があります:

  1. コードを実行すると、wh.WaitOne() が数回呼び出されますが、最初のタイマー イベントだけを待機しているように見えます。すべての「スリープ」関数が削除された場合、コードは最初の関数を待機し、残りをジャンプします。

  2. testfunction の外で safeWaitHandle を作成しました。しかし、タイマーコールバックはテスト関数の実行時にのみ呼び出されるようです。テスト関数を終了すると、実行が停止します。何故ですか?

4

0 に答える 0