RegisterWaitForSingleObject undefined behavior with ManualResetEvent

In one of my projects, I need to schedule a task to run after a certain interval in the background thread. For this I use a mechanism ThreadPool.RegisterWaitForSingleObject. According to the documentation, the first argument may be WaitHandlethat has many subclasses. At first I preferred ManualResetEvent; I use this event for a signal to execute a schedule and exit. Here is my code:

public class ScheduleTester
{
    private long m_LastTicks;
    private RegisteredWaitHandle m_RegisterWaitHandle;
    public ManualResetEvent Event;

    public ScheduleTester()
    {
        Event = new ManualResetEvent(false);
        m_RegisterWaitHandle = ThreadPool.RegisterWaitForSingleObject(Event, new WaitOrTimerCallback(WaitOrTimerCallback), null, 500, false);
        m_LastTicks = DateTime.Now.Ticks;
    }

    private void WaitOrTimerCallback(object state, bool timedOut)
    {
        long ticks = DateTime.Now.Ticks;

        if (timedOut)
        {
            Console.WriteLine(string.Format("Timeout : {0} ... Do scheduled job takes 1 seconds long, Thread ID : {1}", (ticks - m_LastTicks) / 10000f, Thread.CurrentThread.GetHashCode()));                                
        }
        else
        {
            Console.WriteLine(string.Format("Signaled....Unregister , Thread ID : {0}", Thread.CurrentThread.GetHashCode()));

            if (null != m_RegisterWaitHandle)
                m_RegisterWaitHandle.Unregister(null);
        }

        m_LastTicks = ticks;
    }
}

static void Main()
{
    ScheduleTester waitFor = new ScheduleTester();
    Console.ReadKey();
    waitFor.Event.Set();
    Console.ReadKey();
}

I expected to see many lines that inform about a scheduled task, until I press a key to signal an event, and one line noticed that the scheduled execution has been completed. But I see: output1

When ManualResetEventreplaced by AutoResetEvent, all is well. output2

+4
2

, - RegisterWaitForSingleObject . reset , , AutoResetEvent ( ). , "Signaled", , Unregister , RegisterWaitForSingleObject.

+3

, . Debug > Windows > Threads. tp, WaitOrTimerCallback().

, . executeOnlyOnce RWFSO , . false, , , , . AutoResetEvent.

ManualResetEvent, true. :

private void WaitOrTimerCallback(object state, bool timedOut) {
    long ticks = DateTime.Now.Ticks;
    if (timedOut) {
        Console.WriteLine(string.Format("Timeout : {0} ... Do scheduled job takes 1 seconds long, Thread ID : {1}", (ticks - m_LastTicks) / 10000f, Thread.CurrentThread.ManagedThreadId));
        ThreadPool.RegisterWaitForSingleObject(Event, new WaitOrTimerCallback(WaitOrTimerCallback), null, 500, true);
    }
    else {
        Console.WriteLine(string.Format("Signaled....Unregister , Thread ID : {0}", Thread.CurrentThread.ManagedThreadId));
        m_RegisterWaitHandle.Unregister(null);
    }
    m_LastTicks = ticks;
}

, . , .

+3

All Articles