Article ID: 842793 - Last Review: May 18, 2007 - Revision: 1.7

BUG: The Elapsed event of the System.Timers.Timer class is not raised in a Windows service

On This Page

Expand all | Collapse all

SYMPTOMS

You can use the Microsoft .NET Framework to create a new Microsoft Windows service that contains a System.Timers.Timer object. When you run this new Windows service, the Elapsed event of the System.Timers.Timer class may not be raised.

CAUSE

Note In this section, the System.Timers.Timer object is referred to as the Timer object.

In the event handler for the Elapsed event of the Timer object, if you call the Stop method of the Timer object, the reference to the Timer object is lost. The garbage collector then reclaims the memory that is associated with the Timer object. Later, even if you call the Start method of the Timer object to raise the Elapsed event, the call does not work. The Elapsed event is not raised.

WORKAROUND

To work around this problem, obtain the hotfix in the following Microsoft Knowledge Base article:
900822  (http://support.microsoft.com/kb/900822/ ) FIX: When a .NET Framework based application uses the System.Threading.Timer class, the timer event may not be signaled in the .NET Framework 1.1 S900822
Additionally, use a System.Threading.Timer object instead of the System.Timers.Timer object.

STATUS

Microsoft has confirmed that this is a bug in the Microsoft products that are listed in the "Applies to" section.

MORE INFORMATION

Steps to reproduce the behavior

  1. Start Microsoft Visual Studio .NET.
  2. Use Microsoft Visual Basic .NET to create a Windows Service project that is named WinServ1. By default, the Service1.vb file is created.
  3. In Solution Explorer, rename Service1.vb as SimpleService.vb.
  4. Open the code view of the SimpleService.vb file.
  5. Replace the existing code with the following code:
    Imports System
    Imports System.ServiceProcess
    Imports System.Diagnostics
    Imports System.Timers
    
    Public Class SimpleService : Inherits ServiceBase
    
        Protected tmrMain As Timer
    
        Public Shared Sub Main()
            ServiceBase.Run(New SimpleService)
        End Sub
    
        Public Sub New()
            MyBase.New()
            CanPauseAndContinue = True
            ServiceName = "WinServ1"
            tmrMain = New Timer
        End Sub
    
        Protected Overrides Sub OnStart(ByVal args() As String)
            EventLog.WriteEntry("WinServ1 started")
            AddHandler tmrMain.Elapsed, AddressOf tmrMain_Elapsed
            AddHandler tmrMain.Disposed, AddressOf tmrMain_Disposed
            tmrMain.Interval = 1000
            ' Start raising the Elapsed event.
            tmrMain.Enabled = True
        End Sub
    
        Protected Sub tmrMain_Elapsed(ByVal source As Object, ByVal e As ElapsedEventArgs)
            EventLog.WriteEntry("WinServ1")
            ' Stop raising the Elapsed event.
            tmrMain.Stop()
            ' Force garbage collection to make sure that the garbage collector
            ' reclaims the memory that is associated with the tmrMain Timer object.
            GC.Collect()
            ' Start to raise the Elapsed event again.
            tmrMain.Start()
        End Sub
        Protected Sub tmrMain_Disposed(ByVal source As Object, ByVal e As EventArgs)
            EventLog.WriteEntry("WinServ1 timer disposed")
        End Sub
    
    End Class
  6. In Solution Explorer, click SimpleService.vb.
  7. On the View menu, click Properties Window to display the Properties window for the SimpleService.vb service.
  8. Switch to the design view of the SimpleService.vb service.
  9. At the bottom of the Properties window, click the Add Installer link to add the ProjectInstaller.vb file to your project. By default, the ServiceProcessInstaller1 object and the ServiceInstaller1 object are created.
  10. In the Properties window for the ServiceInstaller1 object, set the StartType property to Automatic.
  11. In the Properties window for the ServiceProcessInstaller1 object, set the Account property to LocalSystem.
  12. In Solution Explorer, right-click the WinServ1 project, and then click Properties. The WinServ1 Property Pages dialog box appears.
  13. In the Startup object box, select Sub Main, and then click OK.
  14. On the Build menu, click Build Solution to create the WinServ1.exe file.
  15. Install the Windows service that you created. To do this, run the following command at a Visual Studio .NET command prompt:
    installutil Path\WinServ1.exe
    Note Path is a placeholder for the absolute file path of the WinServ1.exe file that you created in step 14.
  16. Restart your computer.

    The WinServ1 service starts to run and then writes information to the application log of Event Viewer every second. You may soon notice that the WinServ1 service does not write information to the application log. This behavior indicates that the Elapsed event is not being raised.

REFERENCES

For additional information, visit the following Microsoft Developer Network (MSDN) Web sites:
Forcing a garbage collection
http://msdn2.microsoft.com/en-us/library/s5zscb2d(vs.71).aspx (http://msdn2.microsoft.com/en-us/library/s5zscb2d(vs.71).aspx)

Introduction to server-based timers
http://msdn2.microsoft.com/en-us/library/tb9yt5e6(vs.71).aspx (http://msdn2.microsoft.com/en-us/library/tb9yt5e6(vs.71).aspx)

Timer class
http://msdn2.microsoft.com/en-us/library/system.timers.timer(vs.71).aspx (http://msdn2.microsoft.com/en-us/library/system.timers.timer(vs.71).aspx)

Windows Service applications
http://msdn2.microsoft.com/en-us/library/aa984074(VS.71).aspx (http://msdn2.microsoft.com/en-us/library/aa984074(VS.71).aspx)

APPLIES TO
  • Microsoft .NET Framework 1.1
  • Microsoft .NET Framework 1.0
Keywords: 
kbtshoot kbbug kbtimer kbserviceprocess kbsample kbcode KB842793
 

Article Translations

 

Related Support Centers