2

I have data which is constantly being read by many threads. This data needs to be updated daily.

My approach has been to use a ReaderWriterLockSlim to manage access to the data. Every night the first thread to detect the day change applies a WriteLock to the data and updates it.

In order to avoid the constant check for the day change event. I would ideally like to create a System.Timer object as a singleton and have it automatically start and then execute every 24hrs thereafter.

This has been my approach:

First I extended System.Timers to execute the callback on init.

using System.Timers;

namespace Utilities
{
    class AutoStartTimer : Timer
    {
        public AutoStartTimer(ElapsedEventHandler callback, int period):base(period)
        {
            callback(null, null);
            AutoReset = true;
            Elapsed += callback;
            Enabled = true;
        }
    }
}

Then I declared it at a singleton where I needed it.

private static AutoStartTimer _loadDataTimer = 
                                new AutoStartTimer(DataLoader, 86400000); // Daily

This approach is working for me so far. However I would like to know if there are any better ways to implement a Singleton Timer which executes once on initialisation and then for a set period afterwards or if anyone has managed to do this more efficiently without extending the Timer class.

I need to use many of these in my current project so I want to make sure I am using a good approach.

Thanks.

4

2 に答える 2

2

静的クラスの使用:

public static class DayManager
{
     public static readonly object SyncRoot = new object();

     private static readonly Timer dayTimer;

     static DayManager()
     {
         dayTimer = new Timer { AutoReset = true; Enabled = true; Interval = 86400000d };
         dayTimer.Elapsed += OnDayTimerElapsed;
     }

     protected void OnDayTimerElapsed(object sender, ElapsedEventArgs e)
     {
         if(DayPassedEvent != null)
         {
             DayPassedEvent(this, null);
         }
     }

     public event EventHandler DayPassedEvent;
}

ここで、各スレッドで DayPassedEvent をサブスクライブし、Monitor.TryEnter(DayManager.SyncRoot) を使用してタイマー管理クラスのロックを取得する必要があります。これは、1 つのスレッドのみがデータの更新を試行し、残りのスレッドはロックの取得に失敗して存続することを意味します。これの正確な実装はあなたに任せます。

または、ここでタイマー管理クラスから SyncRoot を削除し、既に行っているように別のクラスを使用することもできます。参照用に提供しただけです。

于 2012-11-08T12:30:55.870 に答える
1

私はあなたのためにより良いアプローチを持っています。CodeplexのLightweightSchedulerライブラリを使用します。

指定された時間または間隔でコールバックメソッドの呼び出しを簡単にスケジュールできる軽量のタスクスケジューリングライブラリ。.NET3.5およびSilverlightをサポートします。

このライブラリを使用すると、わずか数行のコードで柔軟なスケジューリング機能をアプリケーションに組み込むことができ、ジョブを構成するための流暢なAPIを提供します。

リンク: http ://scheduling.codeplex.com/

その他のアプローチ:

.NETのタスクスケジューラクラス:http: //msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.aspx

http://taskscheduler.codeplex.com/

http://www.codeproject.com/Articles/1763/Task-Scheduler-Library-for-NET

于 2012-11-08T12:53:19.390 に答える