System.Threading.Timer的奇怪行为

时间:2013-10-01 17:28:30

标签: c# multithreading timer interlocked interlocked-increment

我想了解一下Timer如何使用线程池。我写了以下简单的片段。

class Program
    {
        static private readonly Action Action = () => {
                                                     Thread.SpinWait(100 * 10000);
                                                     Interlocked.Increment(ref _data);
        };

        private static volatile int _data;

        static private Timer _threadCountChecker = new Timer(
            (obj) =>
                {
                    var t = Process.GetCurrentProcess().Threads;
                    Console.WriteLine("Using {0} threads.", t.Count);
                    Console.WriteLine(Program._data);
                }, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));

        static void Main(string[] args)
        {
            var l = new List<Timer>();

            for (int i = 0; i < 10; i++)
            {
                l.Add(new Timer((obj) => Action(), null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)));
            }

            var exitEvent = new ManualResetEvent(false);
            exitEvent.WaitOne();
        }
    }

令人惊讶的是,这是我得到的输出:

  

使用14个线程。 10使用14个线程。 18使用14个线程。 28使用   14个主题。 39使用14个线程。 48使用15个线程。 58使用15   线程。 69使用15个线程。 80使用15个线程。 80使用15   线程。 80使用15个线程。 80使用15个线程。 80使用15   线程。 80使用15个线程。 80使用15个线程。 80使用15   线程。 80使用15个线程。 80使用15个线程。 80使用15   线程。 80使用15个线程。 80使用15个线程。 80使用15   线程。 80使用15个线程。 80使用15个线程。 80使用15   线程。 80使用15个线程。 80使用15个线程。 80使用15   线程。 80使用15个线程。 80使用15个线程。 80使用15   线程。 80使用15个线程。 80使用15个线程。 80使用15   线程。 80使用15个线程。 80使用15个线程。 80使用15   线程。 80使用15个线程。 80使用15个线程。 80使用15   线程。 80使用15个线程。 80

无论我持续运行多长时间,数据变量都保持在80.

有没有人知道为什么变量在前8次迭代中得到更新并且只是停止递增?

1 个答案:

答案 0 :(得分:5)

计时员收集了垃圾。在eventWait.WaitOne()调用之后添加此语句来修复:

  GC.KeepAlive(l);

this answer中详细介绍了GC处理Release版本中局部变量的方式。