Остановка System.Timers.Timer - действительно серьезное усилие. Наиболее серьезная проблема заключается в том, что потоки пула потоков, которые он использует для вызова события Elapsed, могут создавать резервные копии из-за алгоритма планировщика пула потоков. Несколько резервных звонков не являются необычными, технически возможно иметь сотни.
Вам потребуются две синхронизации: одна для обеспечения остановки таймера только тогда, когда не запущен обработчик событий Elapsed, другая для гарантии того, что эти резервные потоки TP не причинят вреда. Как это:
System.Timers.Timer timer = new System.Timers.Timer();
object locker = new object();
ManualResetEvent timerDead = new ManualResetEvent(false);
private void Timer_Elapsed(object sender, ElapsedEventArgs e) {
lock (locker) {
if (timerDead.WaitOne(0)) return;
// etc...
}
}
private void StopTimer() {
lock (locker) {
timerDead.Set();
timer.Stop();
}
}
Рекомендуется установить для свойства AutoReset значение false. С другой стороны, это хрупко, событие Elapsed вызывается из внутреннего метода .NET, который перехватывает Exception. Очень неприятно, ваш таймер перестает работать без какой-либо диагностики. Я не знаю истории, но в MSFT должна была быть другая команда, которая пыхтела и пыхтела в этом беспорядке и писала System.Threading.Timer. Настоятельно рекомендуется.