14

このコードにぶつかっただけで、理解できません。経過したコードを AutoReset true で再実行する代わりに、この設計を使用する理由はありますか?

private readonly Timer Timer = new Timer();

protected override void OnStart(string[] args)
{
    Logger.InfoFormat("Starting {0}.", ServiceName);

    try
    {
        //  If Enabled is set to true and AutoReset is set to false, the Timer raises the Elapsed event only once, the first time the interval elapses.
        Timer.AutoReset = false;
        Timer.Elapsed += Timer_Elapsed;
        Timer.Interval = Settings.Default.ScriptingStatusLifeTime;
        Timer.Start();
    }
    catch (Exception exception)
    {
        Logger.ErrorFormat("An error has occurred while starting {0}.", ServiceName);
        Logger.Error(exception);
        throw;
    }
}

/// <summary>
/// Whenever the Schedule Service time elapses - go to the ScriptingStatus table
/// and delete everything created earlier than 1 hour ago (by default, read from ScriptingStatusLifeTime) 
/// </summary>
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
    try
    {
        //  ScriptingStatusLifeTime defaults to 60 minutes.
        DateTime deleteUntil = DateTime.Now.AddMilliseconds(Settings.Default.ScriptingStatusLifeTime * -1);

        Logger.InfoFormat("Clearing all ScriptingStatus entries with ControlDate before: {0}.", deleteUntil);
        RemoteActivator.Create<RemoteScriptingStatus>().DeleteUntil(deleteUntil);
    }
    catch (Exception exception)
    {
        Logger.Error(exception);
    }
    finally
    {
        Timer.Start();
    }
}

さらに、このコードでメモリリークを探しています。

この投稿を読みました:自動リセットが false に設定されている場合、タイマーは自動的に破棄されますか? これは、Timer オブジェクトを適切に破棄する必要があることを暗示しているようです。現在のファイルに Dispose の呼び出しがありません。この Timer_Elapsed イベントもリークを引き起こしているのでしょうか?

4

1 に答える 1

36

私が理解しているように、AutoResettrueにする必要があるため、発生するタイマーイベントは、イベントの実行にかかる時間がタイムアウト値を超える場所でオーバーラップする可能性があります。

たとえば、タイムアウトは 10 秒ですが、ワークロードは 1 分間です。

ただし、AutoResetas false の場合、タイマー イベントは 1 回だけ発生します。イベントでタイマーを再起動することができ、タイマーは続行できます。

この例では、これはタイマーが 10 秒後に起動できることを意味しますが、イベントが 10 秒以上かかる場合はオーバーラップがなく、作業が完了した後に再起動します。

これは私が行う方法であり、サンプルコードでそれを行う方法でもあります。

補遺:上記は、同期オブジェクトを設定しない場合にのみ当てはまります。これは、スレッド プールで経過イベントが発生するためです。同期オブジェクトを設定すると、一度に 1 つのイベントのみが発生するように、ロックによって経過イベントがブロックされることが期待されます。

于 2013-10-01T16:20:52.170 に答える