У меня есть служба Windows, реализованная на С#, которая должна выполнять некоторую работу так часто. Я реализовал это с помощью System.Threading.Timer
с методом обратного вызова, который отвечает за планирование следующего обратного вызова. У меня возникли проблемы с изящной остановкой (т.е. Утилизации) таймера. Вот несколько упрощенных кодов, которые вы можете запустить в консольном приложении, которое иллюстрирует мою проблему:
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();
Проблема заключается в том, что я получаю ObjectDisposedException
из timer.Change
в потоке обратного вызова, а waitHandle.WaitOne
блокируется. Что я делаю неправильно?
Документация для перегрузки Dispose
, которую я использую, говорит:
Таймер не устанавливается до тех пор, пока все завершенные в настоящий момент обратные вызовы не будут завершены.
Изменить: похоже, что это утверждение из документации может быть неправильным. Может кто-нибудь проверить?
Я знаю, что я мог бы решить проблему, добавив некоторую сигнализацию между обратным вызовом и кодом удаления, как предложил Хенк Холтерман ниже, но я не хочу этого делать, если это абсолютно необходимо.