我试图深入了解计时器如何使用线程池。我写了以下简单的片段。
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 次迭代中更新并停止递增?
计时器被垃圾回收。 在 eventWait.WaitOne(( 调用后添加此语句以解决此问题:
GC.KeepAlive(l);
GC 在发布版本中处理局部变量的方式在此答案中进行了详细说明。