Como faço para parar graciosamente um System.Threading.Timer?

Eu tenho um serviço do Windows implementado em C # que precisa fazer algum trabalho de vez em quando. Eu implementei isso usando umSystem.Threading.Timer com um método de retorno de chamada responsável pelo agendamento do próximo retorno de chamada. Estou tendo problemas para parar graciosamente (ou seja, descartar) o timer. Aqui está um código simplificado que você pode executar em um aplicativo de console que ilustra o meu problema:

const int tickInterval = 1000; // one second

timer = new Timer( state => {
                       // simulate some work that takes ten seconds
                       Thread.Sleep( tickInterval * 10 );

                       // when the work is done, schedule the next callback in one second
                       timer.Change( tickInterval, Timeout.Infinite );
                   },
                   null,
                   tickInterval, // first callback in one second
                   Timeout.Infinite );

// simulate the Windows Service happily running for a while before the user tells it to stop
Thread.Sleep( tickInterval * 3 );

// try to gracefully dispose the timer while a callback is in progress
var waitHandle = new ManualResetEvent( false );
timer.Dispose( waitHandle );
waitHandle.WaitOne();

O problema é que eu recebo umObjectDisposedException detimer.Change no thread de retorno de chamada enquantowaitHandle.WaitOne está bloqueando. O que estou fazendo de errado?

A documentação para oDispose sobrecarga que estou usando diz:

O timer não é descartado até que todos os retornos de chamada enfileirados no momento sejam concluídos.

Edit: Parece que esta declaração da documentação pode estar incorreta. Alguém pode confirmar?

Eu sei que eu poderia contornar o problema adicionando alguma sinalização entre o retorno de chamada e o código de descarte como Henk Holterman sugeriu abaixo, mas eu não quero fazer isso a menos que seja absolutamente necessário.

questionAnswers(4)

yourAnswerToTheQuestion