Jak z wdziękiem zatrzymać system.Threading.Timer?
Mam usługę Windows zaimplementowaną w C #, która musi wykonywać pewne prace co jakiś czas. Zaimplementowałem to za pomocąSystem.Threading.Timer
z metodą wywołania zwrotnego, która jest odpowiedzialna za planowanie następnego wywołania zwrotnego. Mam problem z wdzięcznym zatrzymaniem (tzn. Pozbyciem się) timera. Oto uproszczony kod, który możesz uruchomić w aplikacji konsoli, która ilustruje mój problem:
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();
Problem polega na tym, że dostajęObjectDisposedException
ztimer.Change
w wątku wywołania zwrotnegowaitHandle.WaitOne
blokuje. Co ja robię źle?
Dokumentacja dlaDispose
przeciążenie, którego używam, mówi:
Timer nie jest usuwany, dopóki nie zostaną zakończone wszystkie aktualnie wywołania zwrotne.
Edytuj: Wydaje się, że to stwierdzenie z dokumentacji może być niepoprawne. Czy ktoś może zweryfikować?
Wiem, że mogłem obejść ten problem, dodając sygnalizację między wywołaniem zwrotnym a kodem usuwania, jak zasugerował Henk Holterman poniżej, ale nie chcę tego robić, chyba że jest to absolutnie konieczne.