私はC#で実装された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
fromを取得することです。私は何が間違っているのですか?timer.Change
waitHandle.WaitOne
Dispose
私が使用しているオーバーロードのドキュメントには、次のように書かれています。
現在キューに入れられているすべてのコールバックが完了するまで、タイマーは破棄されません。
編集:ドキュメントからのこのステートメントは正しくない可能性があります。誰かが確認できますか?
Henk Holtermanが以下に提案するように、コールバックと廃棄コードの間にシグナリングを追加することで問題を回避できることはわかっていますが、どうしても必要な場合を除いて、これは行いたくありません。