18

C# で記述された Windows サービスがあります。内部にはタイマーがあり、定期的にいくつかの機能を起動します。だから私のサービスの骨格:

public partial class ArchiveService : ServiceBase
{
    Timer tickTack;
    int interval = 10;
    ...
 
    protected override void OnStart(string[] args)
    {
        tickTack = new Timer(1000 * interval);

        tickTack.Elapsed += new ElapsedEventHandler(tickTack_Elapsed);
        tickTack.Start();
    }

    protected override void OnStop()
    {            
        tickTack.Stop();
    }    
    
    private void tickTack_Elapsed(object sender, ElapsedEventArgs e)
    {
        ...
    }
}

しばらくの間(10〜15日など)機能し、その後停止します。つまり、サービスは実行中と表示されますが、何もしません。私はいくつかのログを作成しましたが、問題はタイマーである可能性があります。これは、インターバル後に tickTack_Elapsed 関数が呼び出されないためです。

設定した時間だけ処理を停止する無限ループを使用して、タイマーなしで書き直すことを考えていました。これもエレガントな解決策ではなく、メモリに関していくつかの副作用があると思います。

タイマーは System.Timers 名前空間から使用され、環境は Windows 2003 です。別のサーバー上の 2 つの異なるサービスでこのアプローチを使用しましたが、どちらもこの動作を生成しています (これが、何らかの形で私のコードまたはコードに接続されていると考えた理由です)。フレームワーク自体)。

誰かがこの動作を経験しましたか? 何が間違っている可能性がありますか?


編集:

両方のサービスを編集しました。1 つはどこでも素晴らしい try-catch を取得し、より多くのログを記録しました。2 つ目は、定期的にタイマー レクリエーションを取得しました。その後、誰も停止していないので、この状況がさらに 1 週​​間続く場合は、この質問を閉じます。皆様、今までありがとうございました。


編集:

何も起こらなかったので、この質問を閉じます。いくつかの変更を加えたということですが、これらの変更はこの問題にはあまり関係がなく、それ以来、両方のサービスは問題なく実行されています。「関連性がなくなったためクローズ」としてマークしてください。

4

7 に答える 7

18

タイマー内の未処理の例外は飲み込まれ、タイマーは黙って強制終了されます

タイマー コードの本体を try-catch ブロックでラップします。

于 2008-12-29T14:39:01.023 に答える
5

これは、タイマー サービスとループ サービスの両方で見たことがあります。通常、タイマーまたはループ スレッドを停止する例外がキャッチされますが、例外回復の一部として再起動されません。

あなたの他の点に...タイマーについて「エレガント」なものはないと思います。私にとっては、タイマー メソッドよりもループ操作をコードで確認する方が簡単です。しかし、エレガンスは主観的です。

メモリの問題?適当に書いてもダメ。Thread.Sleep() が正しく設定されていない場合、プロセッサの負担になる可能性があります。

于 2008-12-29T14:03:02.000 に答える
4

http://support.microsoft.com/kb/842793

これは、フレームワークで複数回再浮上した既知のバグです。

最もよく知られている回避策:タイマーを使用しないでください。ばかげた「while(true)」ループを実行することで、このバグを無効にしました。

マイレージは異なる場合があるため、OS/フレームワークビットの組み合わせで確認してください。

于 2008-12-29T18:30:03.880 に答える
3

興味深い問題です。それが本当に時間に関連するだけの場合(つまり、例外ではない場合)、タイマーを定期的にリサイクルできるかどうか疑問に思います-つまり

private void tickTack_Elapsed(object sender, ElapsedEventArgs e)
{
    CheckForRecycle();
    // ... actual code
}

private void CheckForRecycle()
{
    lock(someLock) {
        if(++tickCount > MAX_TICKS) {
            tickCount = 0;
            tickTack.Stop();
            // re-create timer
            tickTack = new Timer(...);
            tickTack.Elapsed += ...
            tickTack.Start();
        }
    }
}

おそらく、これのチャンクをOnStart/OnStopなどとマージして、重複を減らすことができます。

于 2008-12-29T14:07:21.460 に答える
3

多くの回答者が指摘しているように、例外はタイマーによって飲み込まれます。私の Windows サービスでは、System.Threading.Timer を使用しています。そのタイマーを開始/停止できる Change(...) メソッドがあります。tickTack_Elapsed がタイマー期間よりも長く実行された場合に、例外が発生する可能性のある場所は再入可能性の問題である可能性があります。通常、次のようにタイマー ループを記述します。

    void TimeLoop(object arg)
    {
        stopTimer();

        //Do some stuff

        startTimer();
    }

lock(...)再入可能性から保護するために、メイン ループを使用することもできます。

于 2011-07-07T08:42:41.733 に答える
0

エラーログを確認しましたか? 多分あなたはどういうわけかタイマーを使い果たします。ArchiveService を初期化して OnStart のものをスキップするときに、タイマーを 1 つだけ作成できるかもしれません。

于 2008-12-29T14:02:53.810 に答える
0

私はいくつかのプロジェクトであなたとまったく同じものを作りましたが、問題はありませんでした.

これを引き起こしている可能性のあるコードが tickTac_Elapsed にありますか? 終了しないループやタイマーを停止するエラー、スレッドの使用、それらの終了の待機などのように?

于 2008-12-29T14:05:06.177 に答える