The System.Threading.Timer class provides the functionality we need to periodically perform our write operation. Essentially what we want to do is create a timer when the logging begins and specify a period of time and a method to call using a delegate, or callback, called TimerCallback. The period determines how often the method will be called.
For my implementation, I’m using a static class, which is simply a class with no instance fields and a private constructor (so it cannot be instantiated). I’ve specified a static constructor, which is the ideal place to initiate the timer and set other configuration settings. Another option would be to use a Singleton pattern, and place the startup code in the class’s default constructor.
Figure 9 shows my static constructor. There are a few configuration items that determine whether or not batch updates are enabled and, if so, how frequently they are performed. The last two lines create the timer that links to the Persist method. Figure 10 shows this method, which extracts the XML from the ActivityCollection, clears it, and sends it to the stored procedure (Figure 8) by way of a data access layer method (not shown).
Figure 9: ActivityLogger Static Constructor
static ActivityLogger()
{
activityCollection = new FeaturedItemActivityCollection(100);
int persistDataPeriod = 10;
if(ConfigurationSettings.
AppSettings["FeaturedItemPersistPeriodSeconds"] != null)
{
persistDataPeriod = int.Parse(
ConfigurationSettings.
AppSettings["FeaturedItemPersistPeriodSeconds"]);
}
if(ConfigurationSettings.AppSettings["EnableBatchUpdates"] != null)
{
EnableBatchUpdates = bool.Parse(
ConfigurationSettings.AppSettings["EnableBatchUpdates"]);
}
if(EnableBatchUpdates)
{
TimerCallback callback = new TimerCallback(Persist);
timer = new Timer(callback, null,
new TimeSpan(0,0,0,persistDataPeriod),
new TimeSpan(0, 0, 0, persistDataPeriod));
}
}
Figure 10: Persist Method—Responsible for Performing Batch Update
private static void Persist(object state)
{
if(activityCollection.Count > 0)
{
string xmlData = "";
lock(activityCollection)
{
xmlData = activityCollection.ToString();
activityCollection.Clear();
}
// persist impressions
AspAlliance.Data.FeaturedItem.BulkInsert(xmlData);
}
}