Wie stoppe ich einen System.Threading.Timer ordnungsgemäß?
Ich habe einen Windows-Dienst in C # implementiert, der von Zeit zu Zeit etwas Arbeit erledigen muss. Ich habe dies mit einem implementiertSystem.Threading.Timer
mit einer Rückrufmethode, die für die Planung des nächsten Rückrufs verantwortlich ist. Ich habe Probleme, den Timer ordnungsgemäß zu stoppen (d. H. Zu entsorgen). Hier ist ein vereinfachter Code, den Sie in einer Konsolenanwendung ausführen können, um mein Problem zu veranschaulichen:
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();
Das Problem ist, dass ich einen bekommeObjectDisposedException
vontimer.Change
auf dem Rückrufthread währendwaitHandle.WaitOne
blockiert. Was mache ich falsch?
Die Dokumentation für dieDispose
Überladung, die ich benutze, sagt:
Der Timer wird erst freigegeben, wenn alle derzeit in der Warteschlange befindlichen Rückrufe abgeschlossen sind.
Bearbeiten: Es scheint, dass diese Aussage aus der Dokumentation falsch ist. Kann das jemand verifizieren?
Ich weiß, dass ich das Problem umgehen könnte, indem ich eine Signalisierung zwischen dem Rückruf und dem Entsorgungscode hinzufüge, wie unten von Henk Holterman vorgeschlagen, aber ich möchte dies nicht tun, es sei denn, dies ist absolut notwendig.