Question

I've been attempting to understand how long it takes to "wake" a thread who is waiting on a blocking construct like AutoResetEvent- from what I understood after reading multiple discussions is that windows has some kind of internal clock which "ticks" every 15.6ms (or so) and then decide which threads are scheduled to run next, so I would expect that the time difference between signaling a thread until that thread wakes up would take a random time between 0-15.6ms. So I wrote this small program to test my theory:

static void Main(string[] args)
        {
            double total = 0;
            int max = 100;
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            for (int i = 0; i < max; i++)
            {                
                AutoResetEvent eventHandle = new AutoResetEvent(false);
                double time1 = 0;
                double time2 = 0;
                Thread t1 = new Thread(new ThreadStart(() => time1 = f1(stopwatch, eventHandle)));
                Thread t2 = new Thread(new ThreadStart(() => time2 = f2(stopwatch, eventHandle)));
                t1.Start();
                t2.Start();
                t1.Join();
                t2.Join();
                double diff = time2 - time1;
                total += diff;
                Console.WriteLine("Diff = " + diff.ToString("F4"));
            }
            double avg = total / max;
            Console.WriteLine("Avg = " + avg.ToString("F4"));

            Console.ReadKey();
        }

        static double f1(Stopwatch s, AutoResetEvent eventHandle)
        {
            Thread.Sleep(500);
            double res = s.Elapsed.TotalMilliseconds;
            eventHandle.Set();
            return res;
        }

        static double f2(Stopwatch s, AutoResetEvent eventHandle)
        {
            eventHandle.WaitOne();
            return s.Elapsed.TotalMilliseconds;                        
        }

To my surprise the average wake-up time was around 0.05 milliseconds - so obviously i'm missing something but I don't know what...

Was it helpful?

Solution

No, 15.625 msec is the period of the clock tick interrupt. Which lets the scheduler interrupt a thread if it has been running without blocking and the scheduler decides that another thread should get a turn.

Threads that block will be pre-empted at their WaitXxx() call. Or Sleep() call. Regardless of the clock tick interrupt.

Notable as well is that a sleeping thread can only resume running at a clock interrupt tick, the reason that Thread.Sleep(1) in fact sleeps for 15.6 msec. Timers, DateTime.Now and Environment.TickCount also have that accuracy, the clock is incremented by the interrupt.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top