The Halcyon Days of System.Threading.Timer

Did installing Windows Server 2003 Service Pack 1 break your multithreaded application? My first guess would be that the application uses a class called System.Threading.Timer, which apparently is something the testing dept. of Microsoft does not care much about.

Quite a few people have encountered the same problem.

This also suggests that since the server is otherwise working perfectly well with SP1, Microsoft is not using .NET Framework very extensively in it's own implementations. Given the complexity of IIS, for example, there's bound to be some kind of timer functionality.

Post-SP1, the following code works only for a minute or so - after that the Timer just stops sending the events. Prior to SP1 the service application and the timer have been running continuously for months.

public Timer ServiceTimer=new Timer(); // System.Threading.Timer

private void OnTimer(Object Source, ElapsedEventArgs e) {
  // ... do the periodical stuff
}

public void StartService() {
  ServiceTimer.Interval=PollInterval;
  ServiceTimer.Elapsed+=new ElapsedEventHandler(OnTimer);
  ServiceTimer.Enabled=true;
}

public void StopService() {
  ServiceTimer.Enabled=false;
}

Fortunately it is quite easy to work around the functionality of the Timer object by creating another thread and using the static Thread.Sleep method, but the workaround done with C# does not use native platform methods directly, so it might be unsuitable for very time-critical purposes. .NET Framework has also another server-type timer, System.Timers.Timer - I'm unsure if that still works in server environment.

Here's how I fixed the timer. Note that there is a significant difference in the behavior, which may be very relevant. In the previous example, the time taken to execute the periodical stuff is excluded from the timer interval, ie. the interval between the start time of executions is constant. In the following, the interval between the executions is a constant.

private Thread TimerThread=null;
private bool Running=false;

private void OnTimer() {
  while(Running) {
    // ... do the periodical stuff
    Thread.Sleep(PollInterval);
  }
}

public void StartService() {
  Running=true;
  TimerThread=new Thread(new ThreadStart(OnTimer));
  TimerThread.Start();
}

public void StopService() {
  Running=false;
}
Categories: Programming
Posted by Matias at 26.06.2005 16.54 (12 years ago) | 208 comments

208 comments

Post a new comment


Will be displayed within an image file, hopefully undecipherable to address harvesters.

content licensed under Creative Commons BY-NC-SA - Valid HTML 5