我一直试图理解“唤醒”正在等待AutoResetEvent
这样的阻塞构造的线程需要多长时间 - 从我在阅读多个讨论之后所理解的是Windows有某种内部每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毫秒 - 显然我错过了一些东西,但我不知道是什么......
答案 0 :(得分:6)
不,15.625毫秒是时钟滴答中断的周期。这让调度程序在没有阻塞的情况下中断了一个线程,并且调度程序决定另一个线程应该转向。
阻止的线程将在WaitXxx()调用时被抢占。或者Sleep()通话。无论时钟滴答中断。
值得注意的是,一个休眠线程只能在时钟中断标记处恢复运行,这是Thread.Sleep(1)实际上休眠15.6毫秒的原因。定时器,DateTime.Now和Environment.TickCount也具有该精度,时钟由中断递增。