2012-01-04 16 views
1

私は、15秒ごとに関数を呼び出す一度のタイマーを持っていますが、最初の5回は機能しますが、作成されていても6回は経過しません。C#System.Threading.Timer再帰的更新

スレッドAがスレッドBがデータの新しい要求を送信している間にスレッドAがデータを処理できる場合は、処理時間が15秒を超えることがあります。スレッドAの処理が終了するまで、スレッドBは開始できません。

const int DATAREFRESH = 15000; 

void RequestUpdate() 
{ 
    // Some data processing goes here 
    Console.WriteLine("Update"); 

    // Set the timer 
    Timer t = new Timer(new TimerCallback(TimeOutCallback), null, DATAREFRESH, Timeout.Infinite); 
} 

private void TimeOutCallback(object state) 
{ 
    RequestUpdate(); 
} 

[出力]ウィンドウでは、「更新」が5回表示され、その後は何も表示されません。それは凍結されていない、私は最後の "更新"の後に終了する〜8スレッドを参照してください。

これを無限に動作させるにはどうすればよいですか?

+0

解決しようとしている問題を説明するタイトルを使用してください。 –

+0

どの 'Timer'クラスを使用していますか? – phoog

+0

なぜ、単一のタイマーインスタンスを作成し、コールバックでそれをリセットしないのですか? – phoog

答えて

7

コールバックから新しいタイマーをインスタンス化するのは非常に奇妙なようです。より現実的な例は、タイマーコールバック内で作業を実行する例です。また、あなたは間違ってTimerコンストラクタを呼び出すようです。あなたは、コールバックは、(あなたのケースでは15秒)を定期的に実行したい場合は、以下を使用することができます。

const int DATAREFRESH = 15000; 
private Timer _timer; 

void RequestUpdate() 
{ 
    // Set the timer 
    _timer = new Timer(TimeOutCallback, null, 0, DATAREFRESH); 
} 

private void TimeOutCallback(object state) 
{ 
    // Some data processing goes here 
    Console.WriteLine("Update"); 
} 

はまた、それがコールバックを実行するように、私はタイマーに渡された引数を反転している様子がわかりごと15秒。

+0

はい、それからもう一度やり直したいと思っています... – craig1231

+2

@ craig1231、どうやって引数を入れ替えたのか気づいてください: 'new Timer(TimeOutCallback、null、0、DATAREFRESH);'。タイマーは定期的にコールバックを実行します。 –

+0

これは正しい行に沿ったもののようですが、私は上記の問題を更新しました。 – craig1231

2

はい、ガベージコレクタはタイマオブジェクトを削除しました。この問題は、タイマ参照をローカル変数として宣言することによって開始されました。 RequestUpdate()メソッドが終了すると、タイマーに参照が残っていません。コールバックでさえ、リファレンスを提供するものではありませんが、これは珍しいことですが、スタティックコールバックメソッドを持ち、リークを回避するタイマーと一貫しています。

private Timer dataRefreshTimer; 

void RequestUpdate() 
{ 
    dataRefreshTimer = new Timer(new TimerCallback(TimeOutCallback), null, 0, DATAREFRESH); 
} 

タイマーはコールバックメソッドを含むクラスと少なくとも同じ長住んでいることを保証します:

簡単な修正はそれをあなたのクラスのフィールドを作ることです。

注目すべきは、System.Timers.Timerクラスにこの同じ問題がないことです。 CLRは、有効になっている間、そのようなタイマーが参照されたままであることを保証します。しかし、そうでなければ非常に良いタイマーではない、それを使用しないでください。