Странное поведение System.Threading.Timer
Я пытаюсь понять, как 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 ответ
Таймеры получили мусор. Добавьте этот оператор после вызова eventWait.WaitOne(), чтобы исправить это:
GC.KeepAlive(l);
Способ, которым GC обрабатывает локальные переменные в сборке Release, подробно объясняется в этом ответе.