c#中信号线程的性能

本文关键字:性能 线程 信号线 信号 | 更新日期: 2023-09-27 17:50:38

我一直在试图了解"唤醒"一个正在等待像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毫秒——所以很明显我错过了一些东西,但我不知道是什么。。。

c#中信号线程的性能

否,15.625毫秒是时钟节拍中断的周期。如果一个线程一直在运行而没有阻塞,那么调度程序可以中断该线程,并且调度程序决定另一个线程应该轮到它。

阻塞的线程将在其WaitXxx((调用时被抢占。或者Sleep((调用。无论时钟滴答声中断。

同样值得注意的是,睡眠线程只能在时钟中断时恢复运行,这就是thread.Sleep(1(实际上睡眠15.6毫秒的原因。计时器、DateTime.Now和Environment.TickCount也有这样的精度,时钟会随着中断而增加。