我一直试图理解"唤醒"正在等待阻塞构造的线程需要多长时间AutoResetEvent
- 从我在阅读多个讨论之后理解的是,窗口有某种内部时钟,每15.6ms"滴答"一次(左右)然后决定下一个计划运行哪些线程,所以我希望在线程发出信号直到该线程唤醒之间的时间差需要0-15.6ms之间的随机时间.所以我写了这个小程序来测试我的理论:
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; }
令我惊讶的是,平均唤醒时间约为0.05毫秒 - 显然我错过了一些东西,但我不知道是什么......
不,15.625毫秒是时钟滴答中断的周期.这使调度程序在没有阻塞的情况下中断线程并且调度程序决定另一个线程应该转向时中断线程.
阻止的线程将在WaitXxx()调用时被抢占.或者Sleep()通话.无论时钟滴答中断.
值得注意的是,睡眠线程只能在时钟中断标记处恢复运行,这是Thread.Sleep(1)实际上休眠15.6毫秒的原因.定时器,DateTime.Now和Environment.TickCount也具有该精度,时钟由中断递增.