2

私は、ユーザーが設定した定期的な間隔で、ある時刻から時刻に Web サービスにデータを書き込む必要がある小さな Windows サービスを持っています。

例のために。8:00~22:00まで20分毎

しかし、10回ほどコールバックをトリガーした後、タイマーが停止し、イベントログには何も記録されず、サービスは正常に動作しており、例外がクラッシュしたことはありません。

コードは非常に単純です。

private Dictionary<string, Timer> m_timers = new Dictionary<string, Timer>();

protected override void OnStart(string[] args)
{
      // load settings

      foreach(var settings in userSettings)
      {
         SetUpTimer(settings);
      }
}

private void Callback(Settings settings)
{
    try
    {
       //Write some data to web service
       //Write to event log that web service write suceeded
    }
    catch(Exception ex)
    {
       //Write to event log
    }

    SetUpTimer(settings);
}

private void SetUpTimer(Settings settings)
{
    Timer timer;

    if (m_timers.ContainsKey(settings.Name))
    {
        timer = m_timers.Where(x => x.Key == settings.Name).Select(x => x.Value).FirstOrDefault();
        // Dispose timer (there is rumor that it can slide after few days), just to be sure.

        if (timer != null)
            timer.Dispose();
    }

    TimeSpan timeToFirstRun = settings.TimeFrom - DateTime.Now.TimeOfDay;

    while (timeToFirstRun.TotalHours < 0 || timeToFirstRun > settings.TimeTo)
    {
        timeToFirstRun += TimeSpan.FromMinutes(settings.EveryHowMuch);
    }

    if (timeToFirstRun > settings.TimeTo)
        timeToFirstRun = settings.TimeFrom - DateTime.Now.TimeOfDay + TimeSpan.FromDays(1.0);

    timer = new Timer(Callback, settings, timeToFirstRun, new TimeSpan(-1));

    if (!m_timers.ContainsKey(settings.Name))
    {
        m_timers.Add(settings.Name, timer);
    }

    // Write to event log that it sucessfully set up for next callback
}
4

1 に答える 1

4

さて、あなたはここに本当に大きな欠陥があります:

タイマーを破棄しますが、から削除しませんm_timers。この名前で新しく作成されたタイマーは辞書に追加されることはなく、結果として、ある時点で GC によって収集されます。

さらに、 LINQ クエリと組み合わせて使用​​するTryGetValue代わりに使用する必要があります。ContainsKey

メソッドの上部は次のようになります。

Timer timer;
if(m_timers.TryGetValue(settings.Name, out timer))
{
    timer.Dispose();
    m_timers.Remove(settings.Name);
}
于 2013-02-04T10:00:25.893 に答える